summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPixel <Pixel>2002-05-04 17:53:08 +0000
committerPixel <Pixel>2002-05-04 17:53:08 +0000
commit24fb33726eca4e8c5a88797adc9c17f4d541f543 (patch)
tree72b385bd9e880e699e43c7db3ba12817f0e8e45e
Initial revision
-rw-r--r--AUTHOR4
-rw-r--r--COPYING340
-rw-r--r--FAQ0
-rw-r--r--FAQ.cd203
-rw-r--r--FAQ.lz77207
-rwxr-xr-xMakefile23
-rw-r--r--VP/main_dump.cpp290
-rw-r--r--Xenogears/Decrypt.cpp507
-rwxr-xr-xXenogears/Makefile23
-rw-r--r--Xenogears/Translate.cpp256
-rw-r--r--Xenogears/XenoCD1.map52
-rw-r--r--Xenogears/XenoCD2.map52
-rw-r--r--Xenogears/archive.cpp37
-rw-r--r--Xenogears/build-sector-2.cpp14
-rw-r--r--Xenogears/build-sector.cpp14
-rw-r--r--Xenogears/compil-2.lex254
-rw-r--r--Xenogears/compil.lex383
-rw-r--r--Xenogears/main_dump.cpp291
-rwxr-xr-xXenogears/map2sqr34
-rw-r--r--Xenogears/reinsert.cpp305
-rw-r--r--Xenogears/script-comp.cpp96
-rw-r--r--Xenogears/script-dec.cpp69
-rw-r--r--Xenogears/test-dlz77.cpp7
-rw-r--r--Xenogears/test-lz77.cpp7
-rwxr-xr-xcd-toolbin0 -> 144519 bytes
-rw-r--r--cd-tool.cpp273
-rw-r--r--cdutils.cpp634
-rw-r--r--cdutils.h83
-rw-r--r--crctable.out91
-rw-r--r--crctables142
-rw-r--r--fileutils.cpp50
-rw-r--r--fileutils.h40
-rw-r--r--generic.cpp56
-rw-r--r--generic.h37
-rw-r--r--info-cd.cpp40
-rwxr-xr-xlz77bin0 -> 232764 bytes
-rw-r--r--lz77.cpp757
-rw-r--r--lz77.h60
-rwxr-xr-xyazedcbin0 -> 68824 bytes
-rw-r--r--yazedc.cpp1017
-rw-r--r--yazedc.h142
41 files changed, 6890 insertions, 0 deletions
diff --git a/AUTHOR b/AUTHOR
new file mode 100644
index 0000000..14bc407
--- /dev/null
+++ b/AUTHOR
@@ -0,0 +1,4 @@
+The PSX-Tools Bundle Pack is principaly written by me, Nicolas "Pixel"
+Noble. But those tools were derivated from code by Yazoo, who took code
+from cdrdao.
+
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..5b6e7c6
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/FAQ b/FAQ
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/FAQ
diff --git a/FAQ.cd b/FAQ.cd
new file mode 100644
index 0000000..4a3a92b
--- /dev/null
+++ b/FAQ.cd
@@ -0,0 +1,203 @@
+
+
+
+Q: What is this tools aimed at anyway?
+A: It is designed to handle ISO images you make from CDs.
+
+
+Q: What is an ISO image anyway?
+A: You can create an ISO with free tools like cdrdao in raw mode, or others,
+ like cdrwin, CloneCD, etc...
+
+
+Q: Are all the ISO formats handled?
+A: No. Only raw-2532 images files. Always the file format outputted by CloneCD
+ and cdrwin, and the format outputted by cdrdao with the --read-raw option.
+
+
+Q: Is Nero's file format supported?
+A: No.
+
+
+Q: Why? Nero's a spreaded software!
+A: It's a commercial tool. Since I don't use any commercial tool, and that no
+ free-software generates Nero ISO, it won't be suppored.
+
+
+Q: What is this tool/library able to?
+A: First, you can read/write sectors from/to an iso file. You can also read
+ informations about an iso file. You can extract/insert files from/to
+ an iso file. Depending upon the mode you'll be using, it will compute
+ the right CRC/ECC code for the given sector. The whole in the following
+ (eventually mixed) modes: MODE_1, MODE_2, MODE_2_FORM_1, MODE_2_FORM_2.
+ Additionnaly, it is able to produce patches (.ppf files) instead modifying
+ the iso file, saving you time when you use the right softwares.
+ Actually, it is quite "oriented" on the MODE_2* formats, since it's
+ the PSX's formats.
+
+
+Q: I've heard CDmage or ECCRegen can also correct the sectors for me.
+A: Maybe. Since it only runs on Win32 platforms, I've never tried it.
+
+
+Q: So, what is the goal of this software?
+A: To modify (patch) ISO images. Nothing else. And of course I want it free,
+ opensource, and working on my preffered operating system, Linux. If somebody
+ can make it working for windows (and I think this is easy to do) I will
+ please me. I can't do it right now since I don't really have the opportunity
+ to build Win32 binaries (apart of cygwin's ones)
+
+
+Q: Where does the source code for the CRC/ECC comes from?
+A: Originally, it has been taken from cdrdao. Yazoo has given some
+ modifications to it. Then I've cleaned it up and made some minor
+ modifications on my self. The source code was called 'yazedc'.
+
+
+Q: Do you have the right to do so?
+A: The software is GPL'ed. I've got the right to give modified versions
+ of it, as long as I don't claim the modificated thing it the original,
+ and as long as I mantion the original authors in it.
+
+
+Q: What a strange name, 'yazedc' ?
+A: I've got my own ideas about the name's origin... The easy solution:
+ "YAZoo EDC", where EDC is the field name of one of the things it will
+ recompute. But there is a more... complicated solution I won't give.
+
+
+Q: So, I can modify your code too, create a new tool, and diffuse it?
+A: Yes, as long as you give the full source code, that the new software
+ is also GPL'ed, and that you mantion me as the original writer of the
+ software, you can. Read the GPL carefully, it's very interesting.
+
+
+Q: What is exactly the format of a CD-Rom?
+A: Firstly, when you have a raw sector, you have to understand its primary form.
+ Secondly, the whole CD has an internal format, called the iso9660. The format
+ of the iso9660 is easy to find on the internet. Here is one first easy link:
+ http://www.ccs.neu.edu/home/bchafy/cdb/info/iso9660.txt
+ Then you have two more difficult documents:
+ http://www.ecma.ch/ecma1/stand/ecma-119.htm
+ and
+ http://www.ecma.ch/ecma1/stand/ecma-130.htm
+
+ All those links were taken from the page
+ http://www.ccs.neu.edu/home/bchafy/cdb/info/info.html
+
+ The sector format is a bit complicated to find on the internet. Here is what
+ I've found.
+
+ First you have to know that there is many formats that describe the sector's
+ organisation. Those are called "Books". There is the Red Book, the Yellow
+ Book, the Blue Book, the Green Book, the Orange Book, and the White Book.
+
+ The Red Book is for Audio CD. The Yellow for common CD-Roms. The Blue book
+ for Philips's VideoCD. The Green Book for CD-i and CD-XA. The Orange Book
+ for CD-R cds. And the White Book seems to be a replacement of the Green one.
+
+ This is quite unclear and you have to actually buy the books since they
+ aren't in public domain.
+
+ So the informations I'll give comes from various source of various free
+ softwares. Should I mention two: cdrdao http://cdrdao.sourceforge.net
+ and ECCRegen http://web.tiscali.it/eccregen as the most useful sources.
+
+ Here is the general form of a CD-Rom sector:
+
+ <--------------------------- sector: 2352 bytes ------------------------------>
+ <- Header: 16 bytes -><---------------- Datas: 2336 bytes -------------------->
+
+ Let's move to the header description:
+
+ <--------------------------- header: 16 bytes ------------------------------>
+ <-- sync bytes: 12 bytes --><-- localisation: 3 bytes --><-- mode: 1 byte -->
+
+ The sync bytes are easy: it is always 00 FF FF FF FF FF FF FF FF FF FF 00
+
+ The localisation is the sector "position" described in time. For example,
+ the sector 200000 of a CD is at the "time" 44:28:50. The first is the number
+ of minutes, the second is the number of seconds, in the range 0-59 and the
+ last is the frame number, in the range 0-74. It means there is 75 frames
+ into a second for a CD player. Please note that the CD "begins" at 00:02:00.
+
+ Ok now that we know all this, you can feel the way the localisation is
+ stored. But it is not that easy...
+
+ <-------------------- localisation: 3 bytes -------------------->
+ <-- minute: 1 byte --><-- second: 1 byte --><-- frame: 1 byte -->
+
+ That's seems to be all right *BUT* the fact is that the bytes are stored
+ in packed BCD format. You may know what the BCD format is if you are "old"
+ enough for that. I won't enter into the details so if you want a more
+ description of the BCD format, look into the net. You only have to know that:
+
+unsigned char from_BCD(unsigned char x) {return ((x & 15) + (x & 240) * 10));}
+unsigned char to_BCD(unsigned char x) {return ((x / 10) << 4) | (x % 10));}
+int is_valid_BCD(unsigned char x) {return (((x & 15) < 10) && ((x >> 4) < 10));}
+
+ Last thing: when you look at a BCD packed number, you have to read it in
+ hexadecimal, and then you will see a "decimal" number. So when you count
+ in BCD, you'll have this: 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x10, 0x11, 0x12, etc... You see? You've got a "gap": no 0x0a,
+ 0x0b, 0x0c, etc... So the BCD is only a trick for an easy reading of hexa
+ dumps of various informations.
+
+ All right. This was for the localisation part. The last part is the mode
+ byte. It is really simple actually. It is 0 for an empty sector, 1 for a
+ sector in MODE1, and 2 for a sector in MODE2. Easy as hell.
+
+ Ok here we are: we know the basic form of a CD's sector, and even know the
+ MODE of the sector. Now the datas depends upon the sector mode. Here you have
+ the various kinds:
+
+ <-------------- MODE 1 FORM 1 Sector datas: 2336 bytes ---------------------->
+ <- datas: 2048 bytes -><- EDC: 4 bytes -><- 0s: 8 bytes -><- ECC: 276 bytes ->
+
+ <---------- MODE 1 FORM 2 and also MODE 2 Sector datas: 2336 bytes ---------->
+ <----------------------------- datas: 2336 bytes ---------------------------->
+
+ <-------------- MODE 2 FORM 1 Sector datas: 2336 bytes ---------------------->
+ <- SH: 8 bytes -><- datas: 2048 bytes -><- EDC: 4 bytes -><- ECC: 276 bytes ->
+
+ <-------------- MODE 2 FORM 2 Sector datas: 2336 bytes ---------------------->
+ <- SH: 8 bytes -><---------- datas: 2324 bytes ----------><- spare: 4 bytes ->
+
+ Well, I *really* don't know how to distinguish the different "FORMS" from
+ each others for the MODE 1. Have to look further for this.
+
+ The ECC and EDC controls blocks. The yazedc code can compute them, so
+ don't worry about them.
+
+ The 'SH' (SubHeader) field is the most "complicated" one. Those eight little
+ bits are the only one I'm really not sure of. All of that because you have to
+ buy the Books to find the information. This SubHeader is only found into
+ MODE_2_FORM_1 and MODE_2_FORM_2 sectors.
+
+ Here you have the informations I've been able to gather:
+
+ -) The SubHeader has 8 bytes, but it's twice the same 4 bytes.
+ -) The 4 bytes are described using the following fields:
+ o) 1st byte: File Number (FN)
+ o) 2nd byte: Channel Number (CN)
+ o) 3rd byte: Sub Mode (SM)
+ o) 4st byte: Coding Info (CI)
+ -) I've *never* seen any SubHeader with a FN, CN or CI different from 0,
+ please inform me if you do.
+ -) The Sub Mode byte is a bit field which seems to be described like this:
+ 0: End of Record (EOR)
+ 1: Video
+ 2: Audio
+ 3: Data
+ 4: Trigger
+ 5: Form 2
+ 6: Real Time (RT)
+ 7: End of File (EOF)
+
+ Very last things to know: of course, the PSX has the CDs in MODE 2... So the
+ common files are stored in MODE 2 FORM 1, the STR/XA files are stored in
+ MODE 2 and I've never seen any file stored in MODE 2 FORM 2. And the MODE 2
+ FORM 1 and MODE 2 FORM 2 are also called XA-Mode1 and XA-Mode2 or simplier:
+ XA-1 and XA-2.
+
+ I hope this will help you as it helped me writing this software.
diff --git a/FAQ.lz77 b/FAQ.lz77
new file mode 100644
index 0000000..7bd7e0a
--- /dev/null
+++ b/FAQ.lz77
@@ -0,0 +1,207 @@
+
+
+
+Q: What is the lz77 compression? What is the terminology you used?
+A: The lz77 compression is a quite simple algorithm, which works in stream.
+ You have to "copy" the uncompressed bytes from the stream, and sometime,
+ you encounter what I've called "restart blocks" which tells two things:
+ a backward jump, and a lenght. The jump value tells you of how many bytes
+ you have to "rewind", and the length tells you how many bytes you have to
+ copy from there. For example if you have the compressed stream:
+
+ One Ring to rule them all, <J:27,L:12>find<J:28,L:5>.
+
+ then you will decompress it by:
+
+ One Ring to rule them all, One Ring to find them.
+
+ because when you hit the <J:27,L:12>, it tells you to copy 12 bytes from
+ 27 bytes backward, and when you hit the <J:28,L:5>, it tells you to
+ copy 5 bytes from 28 bytes backward.
+
+
+
+Q: What are the differences between lz77, lzss and lzw?
+A: The lzw is the algorithm name implemented by PKZIP, and thus by WinZIP.
+ But it uses basically the same scheme as the lz77 algorithm. The lzss
+ is the name for a fixed maximum backward length window algorithm.
+ I've named my stuff 'lz77' because it's the generic name for it.
+ The lzw is in fact two algorithms in one: the Huffman and the lz77.
+
+
+
+Q: How is the file stored?
+A: From a general manner, you have a 4 bytes length to know where to stop
+ when you are uncompressing. As you may have noticed, you have normal
+ bytes and compressed blocks. So you can have a bitmap which tells you
+ if the bytes are normal bytes or restart blocks. As an example, let's
+ look the Lord of the Rings compression:
+
+ |Bitmaps | Datas
+ |--------|---------------------------|--------|
+ |00000000| 4f 6e 65 20 52 69 6e 67 |One Ring|
+ |00000000| 20 74 6f 20 72 75 6c 65 | to rule|
+ |00000000| 20 74 68 65 6d 20 61 6c | them al|
+ |00010000| 6c 2c 20<1b 90>66 69 6e 64|l, ..find|
+ |10000000|<1b 20>2e |...|
+
+ If you have a 0 in the bitmap, then you know you have to simply copy the
+ byte you find, and if you have a 1, you have to read the two next bytes,
+ 'unpack' them to find the backward jump and the length, then copy the
+ corresponding bytes. As an exercise, try to find how I've 'packed' the
+ length and the backward jump into the above array.
+
+ Since you need two bytes to write a restart block, you will have to add
+ three to the unpacked length.
+
+ Here is the final form of the packed file:
+
+0000: 31 00 00 00 00 4F 6E 65 20 52 69 6E 67 00 20 74 1 One Ring t
+0010: 6F 20 72 75 6C 65 00 20 74 68 65 6D 20 61 6C 08 o rule them al.
+0020: 6C 2C 20 1B 90 66 69 6E 64 01 1B 20 2E l, ..find.. ..
+
+ Note how the bitmaps are stored.
+
+
+
+Q: How are the jump and length packed?
+A: You may find infos on the net like:
+
+ O3 O2 O1 O0 L3 L2 L1 L0 | OB OA O9 O8 O7 O6 O5 O4
+
+ This means that the two infos are packed like this: the offset (jump) has the
+ four lower bits in the four upper bits of the first byte, then the eight upper
+ bits are directly stored into the second byte. Thus, the backward jump is
+ stored on 12 bits. The length is stored in four bits, and they are stored in
+ the four lower bits of the first byte. So the length may vary from 3 to 18.
+
+
+
+Q: What is the relationship between the schemes into the software and the
+ thing you pasted above?
+A: It's quite easy. The computation formula is the following:
+
+ decomp_length = shift(val1 & scheme.l_mask_1, scheme.l_shft_1) |
+ shift(val2 & scheme.l_mask_2, scheme.l_shft_2);
+ decomp_jump = shift(val1 & scheme.j_mask_1, scheme.j_shft_1) |
+ shift(val2 & scheme.j_mask_2, scheme.j_shft_2);
+
+
+ So, if you want to write the eight parameters for the above thingy, you
+ will have to set them to this:
+
+ l_mask_1 = 0x0f | l_mask_2 = 0x00 | j_mask_1 = 0xf0 | j_mask_2 = 0xff
+ l_shft_1 = 0 | l_shft_2 = 0 | j_shft_1 = -4 | j_shft_2 = 4
+
+ What is he most difficult to understand is the jump value. We want to build
+ the jump value as: OB OA O9 O8 O7 O6 O5 O4 O3 O2 O1 O0.
+
+ Let's first work on the first byte.
+ -) We have to only keep the Ox bits
+ -) Then we have to move them to the right.
+
+ The mask is here to suppress the unwanted bits. So for our case, the mask is
+ 0xf0 since it's the four high bits. The shift is here to move the bits. A
+ negative value means to move them to the right, and a positive means to the
+ left. So since we have to make the bits go to the four lower bits, we have
+ a shift of -4
+
+ For the second byte:
+ -) We keep all the bits, but
+ -) we have to make room for the four bits from the first byte.
+
+ The mask don't have to suppress anything, so it's set to 0xff. And now, the
+ shift is set to 4 to make enough room.
+
+ Finally, the software will build the jump with those four parameters.
+
+
+Q: What are the others parameters?
+A: You have:
+
+ 1iscomp overlap negative 16bits opposite
+
+ This will change the behaviour of the compression/decompression algorithm.
+
+ The 1iscomp will inverse the bitmap from the default. The default is, a 1 in
+ the bitmap is uncompressed.
+
+ The overlap is a boolean to tell the compressor to use the overlap trick.
+ Some roms does use it, but is a little hard to explain here.
+
+ This is the same for the negative trick.
+
+ The 16bits behavior is quite specific to the FF6 PSX. Everything is coded
+ using 16 bits words instead of 8 bits words. And thus, the compression
+ algorithm is more difficult. As for now, it's broken.
+
+ The opposite behavior is to compute the jump offset in a different way.
+ Instead of taking it as the backward jump value, it will be an offset
+ from the maximum backward jump possible.
+
+
+
+Q: What are the overlap and the negative tricks?
+A: You really want to know? *sigh*
+ Ok, here we go. The negative is still the simplier to understand. When you
+ are uncompressing a lz77 stream, you read backward jumps and lengths. The
+ maximum value for a jump and a length are determined on how the two infos
+ are packed into the restart block.
+
+ For example, if you have 12 bits for the jump and 4 for the length, you will
+ have a maximum of 0xfff for the jump and 18 for the length (18 because it's
+ 0xf + 3)
+
+ Here comes the negative trick: when you are uncompressing the first bytes,
+ you will still be able to have a jump which is *beyond* the beginning of the
+ decompressed file. Later, when your file will grow up, this won't be possible
+ anymore of course, since its size will be over the maximum jump size.
+
+ So, sometime, you can consider that *if* you have a negative value, it's not
+ a fault: you just read zeros. Understood? BTW, most of the case, the negative
+ restart will be very near the begin of the file. So if you have to copy five
+ bytes distant of 1000 bytes from the beginning of the file, *this* is
+ probably a fault, or a misunderstood scheme.
+
+
+ Next, the overlap trick. It's more difficult to understand though. You have
+ to understand the decompressor's algorithm a bit. When it hits a restart
+ block, it computes the jump and the length, then it will begin to copy the
+ bytes from the old decompressed datas, one byte after the other.
+
+ So the trick is here: when you are copying the bytes, the algorithm will
+ be able to reuse them immediately for the current copy, since they are
+ already written. The restart block will use "itself".
+
+ Let's have an example:
+
+ If you want to compress the stream:
+
+ 123123123123
+
+ you will have two solutions. Either with, either without the overlap trick.
+ Without the overlap trick, here is the compressed stream:
+
+ 123123<J:6,L:6>
+
+ This is obvious hu? Now, with the overlap trick:
+
+ 123<J:3,L:9>
+
+ Try to take a piece of paper and to decompress those two thingy, maybe this
+ will help you understand.
+
+
+
+Q: When do I have to active the overlap and negative tricks?
+A: Well, for the decompressor, it's not really necessary, because it won't
+ crash if the flags are not enabled. But it will warn you so you will be
+ able to know that the tricks are enabled into the lz77 stream. So if you
+ see that those tricks are enabled, then active the flags so the compressor
+ will be able to take care of them.
+
+ Something else: you may also test if the tricks are working. Maybe they
+ wasn't used when your original lz77 stream was created, but the decompression
+ algorithm used by the game *maybe* is able to handle them.
+
+
diff --git a/Makefile b/Makefile
new file mode 100755
index 0000000..5a3134a
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,23 @@
+#!/usr/bin/make -f
+
+CPPFLAGS=-Wall -g -I. -O3 -mcpu=i686 -pedantic -pedantic-errors -Werror
+CXX=g++
+
+TARGET = lz77 dlz77 yazedc cd-tool
+
+all: ${TARGET}
+
+lz77: lz77.cpp lz77.h generic.cpp generic.h fileutils.h fileutils.cpp
+ ${CXX} ${CPPFLAGS} ${LDFLAGS} -DLZ77_MAIN lz77.cpp generic.cpp fileutils.cpp -o lz77
+
+dlz77: lz77
+ ln -fs lz77 dlz77
+
+yazedc: yazedc.cpp crctables crctable.out
+ ${CXX} ${CPPFLAGS} ${LDFLAGS} yazedc.cpp -DMAIN -o yazedc
+
+cd-tool: cd-tool.cpp cdutils.cpp cdutils.h fileutils.cpp fileutils.h generic.cpp generic.h yazedc.cpp yazedc.h
+ ${CXX} ${CPPFLAGS} ${LDFLAGAS} cd-tool.cpp cdutils.cpp fileutils.cpp yazedc.cpp generic.cpp -o cd-tool
+
+clean:
+ rm -f *.o ${TARGET} compil.c
diff --git a/VP/main_dump.cpp b/VP/main_dump.cpp
new file mode 100644
index 0000000..cf6197d
--- /dev/null
+++ b/VP/main_dump.cpp
@@ -0,0 +1,290 @@
+/*
+ * Valkyrie Profile extractor by Nicolas "Pixel" Noble (nicolas@nobis-crew.org)
+ * Highly based upon Yazoo's Chrono Cross CD extractor
+ *
+ * ******** Original disclaimer by Yazoo ********
+ *
+ * Chrono Cross CD extractor Copyright 2000-2001 by Yazoo (hamm@efrei.fr) Revision 0.1b ANSI C
+ *
+ *
+ * Features:
+ *
+ * Dump the complete content of Chrono Chross CD1/CD2 US and Japanese version It requires a iso
+ * named Chrono1.iso in the same directory
+ *
+ * Todo list:
+ *
+ * Find a way to locate end of the last file Better support for CD2 Dump in subdirectory according
+ * to CD1/CD2 repartition Recompilation in Visual C++ 6 for disk speed optimisation Source comment
+ * and reorganisation Log feature (Optional since you can redirect output with > ) Progression
+ * indicator Better detection of the ISO with error control Major code optimisation Integration in
+ * main Chrono Cross Hacking tool
+ *
+ * ******** End of original disclaimer by Yazoo ********
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "fileutils.h"
+#include "cdutils.h"
+#include "generic.h"
+
+unsigned int tourne = 0;
+
+struct t_index_tab {
+ unsigned long address;
+ long size;
+ long type;
+ long index;
+};
+
+struct t_sequence {
+ unsigned int n;
+ unsigned int sum;
+ char *prefix;
+ char *name;
+ int type;
+};
+
+char *title, *iso_filename, *prefix;
+unsigned long iso_size;
+unsigned int nb_records, nb_seqs = 0;
+struct t_sequence sequences[1000];
+
+long check_iso(FILE * f_iso);
+void read_files(FILE * f_iso);
+void file_dump(FILE * f_iso, unsigned long debut, unsigned long taille, long num, int seq);
+int process_def_file(FILE * f_def);
+
+unsigned char user_data[2352];
+
+int main(int argc, char **argv)
+{
+ FILE * f_def, * f_iso;
+
+ verbosity = 3;
+
+ fprintf(stderr,
+"Valkyrie Profile File Extractor by Nicolas \"Pixel\" Noble\n"
+"Highly based upon the Chrono Cross File Extractor By Yazoo\n\n");
+
+ if (argc != 3) {
+ fprintf(stderr, "Usage: %s <definition_file.sqr> <iso_file_name>\nSee readme.txt for details\n",
+ argv[0]);
+ exit(-1);
+ }
+
+ printm(M_STATUS, "Processing file %s...\n", argv[1]);
+
+ if (!(f_def = fopen(argv[1], "r"))) {
+ printm(M_ERROR, "Unable to open the definition file \"%s\"...\n", argv[1]);
+ exit(-1);
+ }
+
+ if (process_def_file(f_def)) {
+ fclose(f_def);
+ printm(M_ERROR, "Unable to process the definition file \"%s\"...\n", argv[1]);
+ exit(-1);
+ }
+
+ iso_filename = argv[2];
+
+ printm(M_STATUS, "Begin processing iso file.\n");
+ if (!(f_iso = fopen(iso_filename, "r"))) {
+ printm(M_ERROR, "Unable to open the iso file \"%s\"...\n", iso_filename);
+ exit(-1);
+ }
+
+ if (check_iso(f_iso)) {
+ printm(M_ERROR, "Invalid iso file for %s\n", title);
+ printm(M_ERROR, "===> Make sure you are using a Genuine iso file.\n");
+ } else {
+ printm(M_INFO, "Genuine %s iso detected.\n", title);
+ }
+ printm(M_STATUS, "Entering files read sequence\n");
+ read_files(f_iso);
+ fclose(f_iso);
+ exit(0);
+}
+
+/*
+ * Ugly but working... for now
+ */
+int process_def_file(FILE * f_def)
+{
+ char t[1024], *p;
+ unsigned int n, sum = 0;
+
+ if ((p = strchr(fgets(t, 1024, f_def), '\n')) == NULL)
+ return 1;
+ *p = 0;
+ printm(M_INFO, "Read title: %s\n", t);
+ title = strdup(t);
+
+ if (fscanf(f_def, "%lu\n", &iso_size) != 1)
+ return 1;
+ printm(M_INFO, "Read iso size: %lu bytes\n", iso_size);
+
+ if ((p = strchr(fgets(t, 1024, f_def), '\n')) == NULL)
+ return 1;
+ *p = 0;
+ printm(M_INFO, "Read global directory prefix: %s\n", t);
+ prefix = strdup(t);
+
+ if (fscanf(f_def, "%u\n", &nb_records) != 1)
+ return 1;
+ printm(M_INFO, "Read total of records: %u\n", nb_records);
+
+ while (1) {
+ if (fscanf(f_def, "%u\n", &n) != 1)
+ return 1;
+ if (!n) {
+ if (sum == nb_records) {
+ printm(M_INFO, "Definition file seems coherent\n");
+ return 0;
+ } else {
+ printm(M_ERROR, "Definition file incoherent\n");
+ return 1;
+ }
+ }
+ sum += n;
+ sequences[nb_seqs].n = n;
+ sequences[nb_seqs].sum = sum;
+ if ((p = strchr(fgets(t, 1024, f_def), '\n')) == NULL)
+ return 1;
+ *p = 0;
+ sequences[nb_seqs].prefix = strdup(t);
+ if (fscanf(f_def, "%u\n", &n) != 1)
+ return 1;
+ sequences[nb_seqs].type = n;
+ if ((p = strchr(fgets(t, 1024, f_def), '\n')) == NULL)
+ return 1;
+ *p = 0;
+ sequences[nb_seqs].name = strdup(t);
+ printm(M_INFO, "Read definition of sequence %i:\n===> %5i (sum = %5i) chunks of %s (%s)\n",
+ nb_seqs, n, sum, t, sequences[nb_seqs].prefix);
+ nb_seqs++;
+ }
+}
+
+long check_iso(FILE * f_iso)
+{
+ unsigned long length;
+
+ length = filesize(f_iso);
+ printm(M_INFO, "Filesize of iso file %s is %ld bytes\n", iso_filename, length);
+ if (length != iso_size) {
+ return 1;
+ }
+ return 0;
+}
+
+void read_files(FILE * f_iso)
+{
+ t_index_tab index_tab[10000];
+ unsigned char t[8];
+ unsigned long i;
+ unsigned long j;
+ unsigned int seq = 0;
+ unsigned long indexer;
+ struct t_index_tab *p = (struct t_index_tab *) t;
+
+ unsigned char fat[32768];
+
+#define INDEXPOS 24
+
+ sector_seek(f_iso, INDEXPOS);
+ for (i = INDEXPOS; i < (INDEXPOS + 16); i++) {
+ printm(M_INFO, "Reading fat sector %lu\n", i);
+ read_sector(f_iso, &fat[2048 * (i - INDEXPOS)], MODE_2_FORM_1);
+ }
+
+ indexer = 0;
+ for (j = 0; j < 32768; j = j + 7) {
+ t[0] = 0;
+ bcopy((char *) &fat[j], (char *) t + 1, 7);
+ p->address >>= 8;
+ index_tab[indexer] = *p;
+ if (p->size > 0 && p->address != 0) {
+ index_tab[indexer].index = j / 7;
+ printm(M_INFO, "Found a quite valid index: number %4lu, address %6lu, size %3li\n",
+ indexer, index_tab[indexer].address, index_tab[indexer].size);
+ indexer++;
+ if (indexer == nb_records)
+ break;
+ } else {
+ printm(M_WARNING, "Ignored invalid index chunk number %4lu (size = %lu) (%02x %02x %02x %02x %02x %02x %02x)\n",
+ j / 7, -index_tab[indexer].size, t[0], t[1], t[2], t[4], t[5], t[6], t[7]);
+ }
+ }
+ printm(M_STATUS, "Index file generation complete.\n\n");
+
+ for (i = 0; i < nb_records; i++) {
+ if (sequences[seq].sum == i)
+ seq++;
+ index_tab[i].type = sequences[seq].type;
+ if (sequences[seq].type == 0) {
+ printm(M_INFO, "%6lu (%10lu): ignored\n", index_tab[i].address, index_tab[i].size);
+ } else {
+ printm(M_INFO, "%6lu (%10lu): ", index_tab[i].address, index_tab[i].size);
+ file_dump(f_iso, index_tab[i].address, index_tab[i].size, i, seq);
+ if (verbosity >= M_INFO) {
+ fprintf(stderr, "\n");
+ }
+ }
+ }
+ fprintf(stderr, "\n");
+}
+
+void file_dump(FILE * f_iso, unsigned long debut, unsigned long taille, long num, int seq)
+{
+ long i;
+ long nbsects;
+ char nom[1000] = "";
+ char *extention = ".out";
+ char nom_t[1000] = "";
+ int f_out;
+ char type = sequences[seq].type;
+ char ptitbidule[] = "-\\|/";
+
+ sprintf(nom_t, "%ld", num);
+
+ strcat(nom, "./");
+
+ strcat(nom, prefix);
+ strcat(nom, "/");
+ MKDIR(nom);
+
+ strcat(nom, sequences[seq].prefix);
+ strcat(nom, "/");
+ MKDIR(nom);
+
+ if (num < 10)
+ strcat(nom, "0");
+ if (num < 100)
+ strcat(nom, "0");
+ if (num < 1000)
+ strcat(nom, "0");
+ strcat(nom, nom_t);
+
+ strcat(nom, extention);
+ f_out = open(nom, O_WRONLY | O_CREAT | O_TRUNC, 00644);
+ nbsects = taille / sec_sizes[type];
+ if (taille % sec_sizes[type])
+ nbsects++;
+ sector_seek(f_iso, debut);
+ for (i = 0; i < nbsects; i++) {
+ if (verbosity < M_INFO)
+ fprintf(stderr, " (%c)\010\010\010\010\010", ptitbidule[((tourne++) >> 8) % 4]);
+ read_sector(f_iso, user_data, type);
+ if (i != (nbsects - 1)) {
+ write(f_out, user_data, sec_sizes[type]);
+ } else {
+ write(f_out, user_data, taille % sec_sizes[type] ? taille % sec_sizes[type] : sec_sizes[type]);
+ }
+ }
+ close(f_out);
+ fprintf(stderr, " (*) Dumped file number %4ld - type \"%s\" \r", num, sequences[seq].name);
+}
diff --git a/Xenogears/Decrypt.cpp b/Xenogears/Decrypt.cpp
new file mode 100644
index 0000000..2f4d99f
--- /dev/null
+++ b/Xenogears/Decrypt.cpp
@@ -0,0 +1,507 @@
+#include<stdio.h>
+#include<string.h>
+
+void init_table(long table[5000])
+{
+ long i;
+
+ for (i = 0; i < 5000; i++) {
+ table[i] = 0;
+ }
+}
+
+char found_position(long table[5000], int number, FILE * f_source)
+{
+ long position;
+ long i;
+
+ position = ftell(f_source);
+
+ for (i = 0; i < number; i++) {
+ if (table[i] <= position)
+ return (1);
+ }
+ return (0);
+}
+
+long found_next(long table[5000], long script_number, long max_script)
+{
+ long i;
+ long next = 0xFFFF;
+ long actual = table[script_number];
+
+ for (i = 0; i < script_number; i++) {
+ if (table[i] > actual) {
+ if (table[i] < next)
+ next = table[i];
+ }
+ }
+
+ for (i = script_number + 1; i < max_script; i++) {
+ if (table[i] > actual) {
+ if (table[i] < next)
+ next = table[i];
+ }
+ }
+
+ return (next);
+}
+
+void dump_text(FILE * f_source, FILE * f_cible, long table[5000], long script_number,
+ long max_script, unsigned char *length_table, unsigned char *line_table)
+{
+ long next;
+ unsigned char val;
+ char temp_string[2];
+ long position;
+ unsigned char temp1 = 0;
+ unsigned char temp2 = 0;
+ long temp;
+
+ temp_string[1] = NULL;
+
+ next = found_next(table, script_number, max_script);
+
+ fseek(f_source, table[script_number], SEEK_SET);
+
+ fprintf(f_cible, "<Text_block lines:%d width:%d>\n",
+ line_table[script_number], length_table[script_number]);
+
+ position = ftell(f_source);
+
+ while (position < next) {
+ val = 0;
+
+ fread((unsigned char *) &val, 1, 1, f_source);
+
+ if (val == 0x00) // "<Close>"
+ {
+ break;
+ } else if (val == 0x01) // "\n"
+ {
+ fprintf(f_cible, "\n");
+ } else if (val == 0x02) // "<New>"
+ {
+ fprintf(f_cible, "<New>\n");
+ } else if (val == 0x03) // "<Wait>"
+ {
+ fprintf(f_cible, "<Wait>");
+ } else if (val == 0x0F) // "<Delay X>
+ {
+ fread((unsigned char *) &temp1, 1, 1, f_source);
+ fread((unsigned char *) &temp2, 1, 1, f_source);
+ if (temp1 == 0) {
+ fprintf(f_cible, "<Delay %d>", temp2);
+ } else if (temp1 == 5) {
+ switch (temp2) {
+ case 0:
+ fprintf(f_cible, "<Fei>");
+ break;
+ case 1:
+ fprintf(f_cible, "<Elly>");
+ break;
+ case 2:
+ fprintf(f_cible, "<Citan>");
+ break;
+ case 3:
+ fprintf(f_cible, "<Bart>");
+ break;
+ case 4:
+ fprintf(f_cible, "<Billy>");
+ break;
+ case 5:
+ fprintf(f_cible, "<Rico>");
+ break;
+ case 6:
+ fprintf(f_cible, "<Emeralda>");
+ break;
+ case 7:
+ fprintf(f_cible, "<Chu-Chu>");
+ break;
+ case 8:
+ fprintf(f_cible, "<Maria>");
+ break;
+ case 9:
+ fprintf(f_cible, "<Citan2>");
+ break;
+ case 10:
+ fprintf(f_cible, "<Emeralda2>");
+ break;
+ case 11:
+ fprintf(f_cible, "<Weltall>");
+ break;
+ case 12:
+ fprintf(f_cible, "<Weltall-2>");
+ break;
+ case 13:
+ fprintf(f_cible, "<Vierge>");
+ break;
+ case 14:
+ fprintf(f_cible, "<Heimdal>");
+ break;
+ case 15:
+ fprintf(f_cible, "<Brigandier>");
+ break;
+ case 16:
+ fprintf(f_cible, "<Renmazuo>");
+ break;
+ case 17:
+ fprintf(f_cible, "<Stier>");
+ break;
+ case 18:
+ fprintf(f_cible, "<BigChu-chu>");
+ break;
+ case 19:
+ fprintf(f_cible, "<Seibzehn>");
+ break;
+ case 20:
+ fprintf(f_cible, "<Crescens>");
+ break;
+ case 21:
+ fprintf(f_cible, "<Regurus>");
+ break;
+ case 22:
+ fprintf(f_cible, "<Fenrir>");
+ break;
+ case 23:
+ fprintf(f_cible, "<Andvari>");
+ break;
+ case 24:
+ fprintf(f_cible, "<Renmazuo>");
+ break;
+ case 25:
+ fprintf(f_cible, "<Stier-2>");
+ break;
+ case 26:
+ fprintf(f_cible, "<Xenogears>");
+ break;
+ case 27:
+ fprintf(f_cible, "<BARTHOS>");
+ break;
+ case 28:
+ fprintf(f_cible, "<Yggdra>");
+ break;
+ case 128:
+ fprintf(f_cible, "<Perso1>");
+ break;
+ case 129:
+ fprintf(f_cible, "<Perso2>");
+ break;
+ case 130:
+ fprintf(f_cible, "<Perso3>");
+ break;
+ default:
+ fprintf(f_cible, "<Gear %d>", temp2);
+ }
+ } else {
+ fprintf(f_cible, "<Opcode %d %d>", temp1, temp2);
+ }
+ } else if (val == 0x10) // " "
+ {
+ fprintf(f_cible, " ");
+ } else if (val == 0x11) // "+"
+ {
+ fprintf(f_cible, "+");
+ } else if (val == 0x12) // ","
+ {
+ fprintf(f_cible, ",");
+ } else if (val == 0x13) // "-"
+ {
+ fprintf(f_cible, "-");
+ } else if (val == 0x14) // "."
+ {
+ fprintf(f_cible, ".");
+ } else if (val == 0x15) // "/"
+ {
+ fprintf(f_cible, "/");
+ } else if ((val >= 0x16) && (val <= 0x1F)) // "0-9"
+ {
+ temp_string[0] = val + 0x1A;
+ fprintf(f_cible, temp_string);
+ } else if ((val >= 0x20) && (val <= 0x39)) // "A-Z"
+ {
+ temp_string[0] = val + 0x21;
+ fprintf(f_cible, temp_string);
+ } else if (val == 0x3A) // "["
+ {
+ fprintf(f_cible, "[");
+ } else if (val == 0x3B) // "]"
+ {
+ fprintf(f_cible, "]");
+ } else if (val == 0x3C) // "="
+ {
+ fprintf(f_cible, "=");
+ } else if ((val >= 0x3D) && (val <= 0x56)) // "a-z"
+ {
+ temp_string[0] = val + 0x24;
+ fprintf(f_cible, temp_string);
+ } else if (val == 0x57) // "!"
+ {
+ fprintf(f_cible, "!");
+ } else if (val == 0x58) // "\""
+ {
+ fprintf(f_cible, "\"");
+ } else if (val == 0x59) // "#"
+ {
+ fprintf(f_cible, "#");
+ } else if (val == 0x5A) // "%"
+ {
+ fprintf(f_cible, "%%");
+ } else if (val == 0x5B) // "&"
+ {
+ fprintf(f_cible, "&");
+ } else if (val == 0x5C) // "'"
+ {
+ fprintf(f_cible, "'");
+ } else if (val == 0x5D) // "("
+ {
+ fprintf(f_cible, "(");
+ } else if (val == 0x5E) // ")"
+ {
+ fprintf(f_cible, ")");
+ } else if (val == 0x5F) // ":"
+ {
+ fprintf(f_cible, ":");
+ } else if (val == 0x60) // "?"
+ {
+ fprintf(f_cible, "?");
+ } else if (val == 0x61) // "<0>"
+ {
+ fprintf(f_cible, "<0>");
+ } else if (val == 0x62) // "<1>"
+ {
+ fprintf(f_cible, "<1>");
+ } else if (val == 0x63) // "<2>"
+ {
+ fprintf(f_cible, "<2>");
+ } else if (val == 0x64) // "<3>"
+ {
+ fprintf(f_cible, "<3>");
+ } else if (val == 0x65) // "<4>"
+ {
+ fprintf(f_cible, "<4>");
+ } else if (val == 0x66) // "<5>"
+ {
+ fprintf(f_cible, "<5>");
+ } else if (val == 0x67) // "<6>"
+ {
+ fprintf(f_cible, "<6>");
+ } else if (val == 0x68) // "<7>"
+ {
+ fprintf(f_cible, "<7>");
+ } else if (val == 0x69) // "<8>"
+ {
+ fprintf(f_cible, "<8>");
+ } else if (val == 0x6A) // "<9>"
+ {
+ fprintf(f_cible, "<9>");
+ } else if (val == 0x6B) // "<%>"
+ {
+ fprintf(f_cible, "<%%>");
+ } else if (val == 0x6C) // "<&>"
+ {
+ fprintf(f_cible, "<&>");
+ } else if (val == 0x6D) // "*"
+ {
+ fprintf(f_cible, "*");
+ } else if (val == 0x6E) // "<C>"
+ {
+ fprintf(f_cible, "<C>");
+ } else if (val == 0x6F) // "<S>"
+ {
+ fprintf(f_cible, "<S>");
+ } else if (val == 0x70) // "<T>"
+ {
+ fprintf(f_cible, "<T>");
+ } else if (val == 0x71) // "<*>"
+ {
+ fprintf(f_cible, "<*>");
+ } else if (val == 0x72) // "<R>"
+ {
+ fprintf(f_cible, "<R>");
+ } else if (val == 0x73) // "<L>"
+ {
+ fprintf(f_cible, "<L>");
+ } else if (val == 0x74) // "<U>"
+ {
+ fprintf(f_cible, "<U>");
+ } else if (val == 0x75) // "<U>"
+ {
+ fprintf(f_cible, "<D>");
+ } else if (val == 0x76) // "<.>"
+ {
+ fprintf(f_cible, "<.>");
+ } else if (val == 0x77) // "<:>"
+ {
+ fprintf(f_cible, "<:>");
+ } else if (val == 0x79) // "</>"
+ {
+ fprintf(f_cible, "</>");
+ } else if (val == 0x7A) // "<..>"
+ {
+ fprintf(f_cible, "<..>");
+ } else if (val == 0x7B) // "<`>"
+ {
+ fprintf(f_cible, "<`>");
+ } else if (val == 0x7D) // "<+>"
+ {
+ fprintf(f_cible, "<+>");
+ } else if (val == 0x7E) // "<->"
+ {
+ fprintf(f_cible, "<->");
+ } else if (val == 0x7F) // "<X>"
+ {
+ fprintf(f_cible, "<X>");
+ } else if (val == 0x80) // "<[>"
+ {
+ fprintf(f_cible, "<[>");
+ } else if (val == 0x81) // "<]>"
+ {
+ fprintf(f_cible, "<]>");
+ } else if (val == 0x82) // "<%>"
+ {
+ fprintf(f_cible, "<%%>");
+ } else if (val == 0x83) // "<&>"
+ {
+ fprintf(f_cible, "<&>");
+ } else if (val == 0x84) // "<(>"
+ {
+ fprintf(f_cible, "<(>");
+ } else if (val == 0x85) // "<)>"
+ {
+ fprintf(f_cible, "<)>");
+ } else if (val == 0x86) // "<#>"
+ {
+ fprintf(f_cible, "<#>");
+ } else if (val == 0x87) // "`"
+ {
+ fprintf(f_cible, "`");
+ } else if (val == 0x88) // "°"
+ {
+ fprintf(f_cible, "°");
+ } else if (val == 0x89) // "<=>"
+ {
+ fprintf(f_cible, "<=>");
+ } else if (val == 0x8A) // "<?>"
+ {
+ fprintf(f_cible, "<?>");
+ } else if (val == 0x8B) // "<!>"
+ {
+ fprintf(f_cible, "<!>");
+ } else if (val == 0x8C) // "_"
+ {
+ fprintf(f_cible, "_");
+ } else if (val == 0x8D) // "~"
+ {
+ fprintf(f_cible, "~");
+ } else if (val == 0x8E) // "<...>"
+ {
+ fprintf(f_cible, "<...>");
+ } else if (val == 0x8F) // "<'>"
+ {
+ fprintf(f_cible, "<'>");
+ } else if (val == 0xFE) // "<Extra1 X>
+ {
+ fread((unsigned char *) &temp1, 1, 1, f_source);
+ fprintf(f_cible, "<Extra1 %d>", temp1);
+ } else if (val == 0xFF) // "<Extra2 X>
+ {
+ fread((unsigned char *) &temp1, 1, 1, f_source);
+ fprintf(f_cible, "<Extra2 %d>", temp1);
+ } else {
+ fprintf(f_cible, "<Bare %X>", val);
+ }
+
+ position = ftell(f_source);
+ }
+ fprintf(f_cible, "\n<End_of_block>\n\n");
+}
+
+int decrypt(FILE * f_source, FILE * f_cible, int room_number)
+{
+ long i, j;
+ long table[5000];
+ unsigned char line_table[5000];
+ unsigned char length_table[5000];
+ long script_number = 0;
+ long temp = 0;
+ char temp_char;
+ int counter = 0;
+
+ fread((long *) &script_number, 4, 1, f_source);
+
+ if (script_number == 0x0000FFFF)
+ return (1);
+
+ script_number = (script_number++);
+
+ fprintf(f_cible, "<Blocks:%i>\n", script_number);
+ init_table(table);
+
+ i = j = 0;
+
+ while (i < script_number) {
+ fread((long *) &temp, 2, 1, f_source);
+ if (table[j - 1] != temp)
+ table[j++] = temp;
+ i++;
+ }
+
+ script_number = j;
+
+ for (i = 0; i < script_number; i++) {
+ fread((unsigned char *) &length_table[i], 1, 1, f_source);
+ fread((unsigned char *) &line_table[i], 1, 1, f_source);
+ }
+
+ fseek(f_source, table[script_number - 1], SEEK_SET);
+
+ do {
+ fread((char *) &temp_char, 1, 1, f_source);
+ counter++;
+ } while (temp_char != 0);
+
+ table[script_number] = ftell(f_source);
+
+ for (i = 0; i < script_number; i++) {
+ dump_text(f_source, f_cible, table, i, script_number, length_table, line_table);
+ }
+
+ return (0);
+}
+
+int main(void)
+{
+ int i;
+ char file_name[100];
+ FILE *f_source, *f_cible;
+
+ for (i = 0; i < 730; i++) {
+ printf("%d\n", i);
+ sprintf(file_name, "xeno_d1/ROOMS/%04d/script.comp", i);
+ f_source = fopen(file_name, "rb");
+
+ sprintf(file_name, "xeno_d1/ROOMS/%04d/script.txt", i);
+
+ if (f_source != NULL) {
+ f_cible = fopen(file_name, "w");
+ decrypt(f_source, f_cible, 5);
+ fclose(f_source);
+ fclose(f_cible);
+ }
+ }
+ for (i = 0; i < 730; i++) {
+ printf("%d\n", i);
+ sprintf(file_name, "xeno_d2/ROOMS/%04d/script.comp", i);
+ f_source = fopen(file_name, "rb");
+
+ sprintf(file_name, "xeno_d2/ROOMS/%04d/script.txt", i);
+
+ if (f_source != NULL) {
+ f_cible = fopen(file_name, "w");
+ decrypt(f_source, f_cible, 5);
+ fclose(f_source);
+ fclose(f_cible);
+ }
+ }
+}
diff --git a/Xenogears/Makefile b/Xenogears/Makefile
new file mode 100755
index 0000000..22d6392
--- /dev/null
+++ b/Xenogears/Makefile
@@ -0,0 +1,23 @@
+#!/usr/bin/make -f
+
+CPPFLAGS=-Wall -g -I. -O3 -mcpu=i686
+CXX=g++
+
+TARGET = lz77 dlz77 yazedc cd-tool
+
+all: ${TARGET}
+
+lz77: lz77.cpp lz77.h generic.cpp generic.h fileutils.h fileutils.cpp
+ ${CXX} ${CPPFLAGS} ${LDFLAGS} -DLZ77_MAIN lz77.cpp generic.cpp fileutils.cpp -o lz77
+
+dlz77: lz77
+ ln -fs lz77 dlz77
+
+yazedc: yazedc.cpp crctables crctable.out
+ ${CXX} ${CPPFLAGS} ${LDFLAGS} yazedc.cpp -DMAIN -o yazedc
+
+cd-tool: cd-tool.cpp cdutils.cpp cdutils.h fileutils.cpp fileutils.h generic.cpp generic.h yazedc.cpp yazedc.h
+ ${CXX} ${CPPFLAGS} ${LDFLAGAS} cd-tool.cpp cdutils.cpp fileutils.cpp yazedc.cpp generic.cpp -o cd-tool
+
+clean:
+ rm -f *.o ${TARGET} compil.c
diff --git a/Xenogears/Translate.cpp b/Xenogears/Translate.cpp
new file mode 100644
index 0000000..3f85437
--- /dev/null
+++ b/Xenogears/Translate.cpp
@@ -0,0 +1,256 @@
+#include <stdio.h>
+#include <string.h>
+
+void dump_text(FILE * f_source, FILE * f_cible)
+{
+ unsigned char val;
+ unsigned char temp1 = 0;
+ unsigned char temp2 = 0;
+
+ while (!feof(f_source)) {
+ val = 0;
+
+ fread((unsigned char *) &val, 1, 1, f_source);
+
+ if (val == 0x00) // "<Close>"
+ {
+// break;
+ fprintf(f_cible, "<EOF>\n");
+ } else if (val == 0x01) // "\n"
+ {
+ fprintf(f_cible, "\n");
+ } else if (val == 0x02) // "<New>"
+ {
+ fprintf(f_cible, "<New>\n");
+ } else if (val == 0x03) // "<Wait>"
+ {
+ fprintf(f_cible, "<Wait>");
+ } else if (val == 0x0F) // "<Delay X>
+ {
+ fread((unsigned char *) &temp1, 1, 1, f_source);
+ fread((unsigned char *) &temp2, 1, 1, f_source);
+ if (temp1 == 0) {
+ fprintf(f_cible, "<Delay %d>", temp2);
+ } else if (temp1 == 5) {
+ fprintf(f_cible, "<Gear %d>", temp2);
+ } else {
+ fprintf(f_cible, "<Opcode %d %d>", temp1, temp2);
+ }
+ } else if (val == 0x10) // " "
+ {
+ fprintf(f_cible, " ");
+ } else if (val == 0x11) // "+"
+ {
+ fprintf(f_cible, "+");
+ } else if (val == 0x12) // ","
+ {
+ fprintf(f_cible, ",");
+ } else if (val == 0x13) // "-"
+ {
+ fprintf(f_cible, "-");
+ } else if (val == 0x14) // "."
+ {
+ fprintf(f_cible, ".");
+ } else if (val == 0x15) // "/"
+ {
+ fprintf(f_cible, "/");
+ } else if ((val >= 0x16) && (val <= 0x1F)) // "0-9"
+ {
+ fprintf(f_cible, "%c", val + 0x1a);
+ } else if ((val >= 0x20) && (val <= 0x39)) // "A-Z"
+ {
+ fprintf(f_cible, "%c", val + 0x21);
+ } else if (val == 0x3A) // "["
+ {
+ fprintf(f_cible, "[");
+ } else if (val == 0x3B) // "]"
+ {
+ fprintf(f_cible, "]");
+ } else if (val == 0x3C) // "="
+ {
+ fprintf(f_cible, "=");
+ } else if ((val >= 0x3D) && (val <= 0x56)) // "a-z"
+ {
+ fprintf(f_cible, "%c", val + 0x24);
+ } else if (val == 0x57) // "!"
+ {
+ fprintf(f_cible, "!");
+ } else if (val == 0x58) // "\""
+ {
+ fprintf(f_cible, "\"");
+ } else if (val == 0x59) // "#"
+ {
+ fprintf(f_cible, "#");
+ } else if (val == 0x5A) // "%"
+ {
+ fprintf(f_cible, "%%");
+ } else if (val == 0x5B) // "&"
+ {
+ fprintf(f_cible, "&");
+ } else if (val == 0x5C) // "'"
+ {
+ fprintf(f_cible, "'");
+ } else if (val == 0x5D) // "("
+ {
+ fprintf(f_cible, "(");
+ } else if (val == 0x5E) // ")"
+ {
+ fprintf(f_cible, ")");
+ } else if (val == 0x5F) // ":"
+ {
+ fprintf(f_cible, ":");
+ } else if (val == 0x60) // "?"
+ {
+ fprintf(f_cible, "?");
+ } else if (val == 0x61) // "<0>"
+ {
+ fprintf(f_cible, "<0>");
+ } else if (val == 0x62) // "<1>"
+ {
+ fprintf(f_cible, "<1>");
+ } else if (val == 0x63) // "<2>"
+ {
+ fprintf(f_cible, "<2>");
+ } else if (val == 0x64) // "<3>"
+ {
+ fprintf(f_cible, "<3>");
+ } else if (val == 0x65) // "<4>"
+ {
+ fprintf(f_cible, "<4>");
+ } else if (val == 0x66) // "<5>"
+ {
+ fprintf(f_cible, "<5>");
+ } else if (val == 0x67) // "<6>"
+ {
+ fprintf(f_cible, "<6>");
+ } else if (val == 0x68) // "<7>"
+ {
+ fprintf(f_cible, "<7>");
+ } else if (val == 0x69) // "<8>"
+ {
+ fprintf(f_cible, "<8>");
+ } else if (val == 0x6A) // "<9>"
+ {
+ fprintf(f_cible, "<9>");
+ } else if (val == 0x6B) // "<%>"
+ {
+ fprintf(f_cible, "<%%>");
+ } else if (val == 0x6C) // "<&>"
+ {
+ fprintf(f_cible, "<&>");
+ } else if (val == 0x6D) // "*"
+ {
+ fprintf(f_cible, "*");
+ } else if (val == 0x6E) // "<C>"
+ {
+ fprintf(f_cible, "<C>");
+ } else if (val == 0x6F) // "<S>"
+ {
+ fprintf(f_cible, "<S>");
+ } else if (val == 0x70) // "<T>"
+ {
+ fprintf(f_cible, "<T>");
+ } else if (val == 0x71) // "<*>"
+ {
+ fprintf(f_cible, "<*>");
+ } else if (val == 0x72) // "<R>"
+ {
+ fprintf(f_cible, "<R>");
+ } else if (val == 0x73) // "<L>"
+ {
+ fprintf(f_cible, "<L>");
+ } else if (val == 0x74) // "<U>"
+ {
+ fprintf(f_cible, "<U>");
+ } else if (val == 0x75) // "<U>"
+ {
+ fprintf(f_cible, "<D>");
+ } else if (val == 0x76) // "<.>"
+ {
+ fprintf(f_cible, "<.>");
+ } else if (val == 0x77) // "<:>"
+ {
+ fprintf(f_cible, "<:>");
+ } else if (val == 0x79) // "</>"
+ {
+ fprintf(f_cible, "</>");
+ } else if (val == 0x7A) // "<..>"
+ {
+ fprintf(f_cible, "<..>");
+ } else if (val == 0x7B) // "<`>"
+ {
+ fprintf(f_cible, "<`>");
+ } else if (val == 0x7D) // "<+>"
+ {
+ fprintf(f_cible, "<+>");
+ } else if (val == 0x7E) // "<->"
+ {
+ fprintf(f_cible, "<->");
+ } else if (val == 0x7F) // "<X>"
+ {
+ fprintf(f_cible, "<X>");
+ } else if (val == 0x80) // "<[>"
+ {
+ fprintf(f_cible, "<[>");
+ } else if (val == 0x81) // "<]>"
+ {
+ fprintf(f_cible, "<]>");
+ } else if (val == 0x82) // "<%>"
+ {
+ fprintf(f_cible, "<%%>");
+ } else if (val == 0x83) // "<&>"
+ {
+ fprintf(f_cible, "<&>");
+ } else if (val == 0x84) // "<(>"
+ {
+ fprintf(f_cible, "<(>");
+ } else if (val == 0x85) // "<)>"
+ {
+ fprintf(f_cible, "<)>");
+ } else if (val == 0x86) // "<#>"
+ {
+ fprintf(f_cible, "<#>");
+ } else if (val == 0x87) // "`"
+ {
+ fprintf(f_cible, "`");
+ } else if (val == 0x88) // "°"
+ {
+ fprintf(f_cible, "°");
+ } else if (val == 0x89) // "<=>"
+ {
+ fprintf(f_cible, "<=>");
+ } else if (val == 0x8A) // "<?>"
+ {
+ fprintf(f_cible, "<?>");
+ } else if (val == 0x8B) // "<!>"
+ {
+ fprintf(f_cible, "<!>");
+ } else if (val == 0x8C) // "_"
+ {
+ fprintf(f_cible, "_");
+ } else if (val == 0x8D) // "~"
+ {
+ fprintf(f_cible, "~");
+ } else if (val == 0x8E) // "<...>"
+ {
+ fprintf(f_cible, "<...>");
+ } else if (val == 0x8F) // "<'>"
+ {
+ fprintf(f_cible, "<'>");
+ } else if (val == 0xFE) // "<Extra1 X>
+ {
+ fread((unsigned char *) &temp1, 1, 1, f_source);
+ fprintf(f_cible, "<Extra1 %d>", temp1);
+ } else if (val == 0xFF) // "<Extra2 X>
+ {
+ fread((unsigned char *) &temp1, 1, 1, f_source);
+ fprintf(f_cible, "<Extra2 %d>", temp1);
+ } else {
+ fprintf(f_cible, "<Bare %X>", val);
+ }
+ }
+}
+
+int main(void) {
+ dump_text(stdin, stdout);
+}
diff --git a/Xenogears/XenoCD1.map b/Xenogears/XenoCD1.map
new file mode 100644
index 0000000..8649f1b
--- /dev/null
+++ b/Xenogears/XenoCD1.map
@@ -0,0 +1,52 @@
+Xenogears CD1
+718738272
+xeno_d1
+3728
+ 0 16 VIDEOS 2 Videos
+ 17 17 SYSTEM 3 Codec MDEC
+ 18 18 SYSTEM 3 System.cnf
+ 19 19 SLUS 3 slus 00664
+ 20 25 BOOT 3 Boot system following SLUS
+ 26 37 BFCODE 3 Battle field code and datas
+ 38 86 MISC05 3 Misc part 05
+ 87 93 MISC06 3 Misc part 06
+ 94 239 MISC07 3 Misc part 07
+ 240 250 MISC08 3 Misc part 08
+ 251 252 MISC09 3 Misc part 09
+ 253 285 MISC10 3 Misc part 10
+ 286 376 HEADS 3 Heads shown in dialogs
+ 377 383 MISC12 3 Misc part 12
+ 384 1843 ROOMS 3 Rooms
+1844 1988 MISC14 3 Misc part 14
+1989 2109 MISC15 3 Misc part 15
+2110 2197 TIMS 3 Various TIM files
+2198 2216 BUNCH 3 Bunch of various files
+2217 2220 MISC18 3 Misc part 18
+2221 2373 MISC19 3 Misc part 19
+2374 2375 MISC20 3 Misc part 20
+2376 2525 MISC21 3 Misc part 21
+2526 2747 BATTLE 3 Battle infos
+2748 2978 MISC23 3 Misc part 23
+2979 3518 MISC24 3 Misc part 24
+3519 3534 MISC25 3 Misc part 25
+3535 3551 MISC26 3 Misc part 26
+3552 3553 SAVE 3 Save system
+3554 3556 MISC28 3 Misc part 28
+3557 3566 MAPS 3 Map 01
+3567 3576 MAPS 3 Map 02
+3577 3586 MAPS 3 Map 03
+3587 3596 MAPS 3 Map 04
+3597 3606 MAPS 3 Map 05
+3607 3616 MAPS 3 Map 06
+3617 3626 MAPS 3 Map 07
+3627 3636 MAPS 3 Map 08
+3637 3646 MAPS 3 Map 09
+3647 3656 MAPS 3 Map 10
+3657 3666 MAPS 3 Map 11
+3667 3676 MAPS 3 Map 12
+3677 3686 MAPS 3 Map 13
+3687 3696 MAPS 3 Map 14
+3697 3706 MAPS 3 Map 15
+3707 3716 MAPS 3 Map 16
+3717 3726 MAPS 3 Map 17
+3727 3727 TRASH 0 Zero padding
diff --git a/Xenogears/XenoCD2.map b/Xenogears/XenoCD2.map
new file mode 100644
index 0000000..4c491f7
--- /dev/null
+++ b/Xenogears/XenoCD2.map
@@ -0,0 +1,52 @@
+Xenogears CD2
+688700880
+xeno_d2
+3723
+ 0 11 VIDEOS 2 Videos
+ 12 12 SYSTEM 3 Codec MDEC
+ 13 13 SYSTEM 3 System.cnf
+ 14 14 SLUS 3 slus 00669
+ 15 20 BOOT 3 Boot system following SLUS
+ 21 32 BFCODE 3 Battle field code and datas
+ 33 81 MISC05 3 Misc part 05
+ 82 88 MISC06 3 Misc part 06
+ 89 234 MISC07 3 Misc part 07
+ 235 245 MISC08 3 Misc part 08
+ 246 247 MISC09 3 Misc part 09
+ 248 280 MISC10 3 Misc part 10
+ 281 371 HEADS 3 Heads shown in dialogs
+ 372 378 MISC12 3 Misc part 12
+ 379 1838 ROOMS 3 Rooms
+1839 1983 MISC14 3 Misc part 14
+1984 2104 MISC15 3 Misc part 15
+2105 2192 TIMS 3 Various TIM files
+2193 2211 BUNCH 3 Bunch of various files
+2212 2215 MISC18 3 Misc part 18
+2216 2368 MISC19 3 Misc part 19
+2369 2370 MISC20 3 Misc part 20
+2371 2520 MISC21 3 Misc part 21
+2521 2742 BATTLE 3 Battle infos
+2743 2973 MISC23 3 Misc part 23
+2974 3513 MISC24 3 Misc part 24
+3514 3529 MISC25 3 Misc part 25
+3530 3546 MISC26 3 Misc part 26
+3547 3548 SAVE 3 Save system
+3549 3551 MISC28 3 Misc part 28
+3552 3561 MAPS 3 Map 01
+3562 3571 MAPS 3 Map 02
+3572 3581 MAPS 3 Map 03
+3582 3591 MAPS 3 Map 04
+3592 3601 MAPS 3 Map 05
+3602 3611 MAPS 3 Map 06
+3612 3621 MAPS 3 Map 07
+3622 3631 MAPS 3 Map 08
+3632 3641 MAPS 3 Map 09
+3642 3651 MAPS 3 Map 10
+3652 3661 MAPS 3 Map 11
+3662 3671 MAPS 3 Map 12
+3672 3681 MAPS 3 Map 13
+3682 3691 MAPS 3 Map 14
+3692 3701 MAPS 3 Map 15
+3702 3711 MAPS 3 Map 16
+3712 3721 MAPS 3 Map 17
+3722 3722 TRASH 0 Zero padding
diff --git a/Xenogears/archive.cpp b/Xenogears/archive.cpp
new file mode 100644
index 0000000..6701c2c
--- /dev/null
+++ b/Xenogears/archive.cpp
@@ -0,0 +1,37 @@
+#include <stdio.h>
+#include <values.h>
+#include <stdlib.h>
+#include "fileutils.h"
+
+void dearchive(FILE * f) {
+ long nb;
+ long * address;
+ char fname[100];
+ int i;
+ FILE * f_out;
+
+ fread(&nb, 4, 1, f);
+ nb++;
+ fprintf(stderr, "Reading index... (%li elements)\n", nb);
+
+ address = (long *) malloc(nb * sizeof(long) + 1);
+
+ for (i = 0; i < nb; i++) {
+ fread(address + i, 4, 1, f);
+ }
+ address[nb] = MAXINT;
+
+ for (i = 0; i < nb; i++) {
+ fprintf(stderr, "Dumping file %i\n", i);
+ sprintf(fname, "part-%i.lz", i);
+ f_out = fopen(fname, "wb");
+ copy(fileno(f), fileno(f_out), address[i + 1] - address[i]);
+ fclose(f_out);
+ }
+
+ free(address);
+}
+
+int main(void) {
+ dearchive(stdin);
+}
diff --git a/Xenogears/build-sector-2.cpp b/Xenogears/build-sector-2.cpp
new file mode 100644
index 0000000..6ab7835
--- /dev/null
+++ b/Xenogears/build-sector-2.cpp
@@ -0,0 +1,14 @@
+#include <stdio.h>
+#include "yazedc.h"
+
+int main(void) {
+ unsigned char datas[2352];
+
+ fread(datas, 2352, 1, stdin);
+ minute = datas[12];
+ second = datas[13];
+ frame = datas[14];
+ fprintf(stderr, "Sector info: %2i:%02i:%04i\n", minute, second, frame);
+ do_encode_L2(datas, MODE_2, 0);
+ fwrite(datas, 2352, 1, stdout);
+}
diff --git a/Xenogears/build-sector.cpp b/Xenogears/build-sector.cpp
new file mode 100644
index 0000000..3effc35
--- /dev/null
+++ b/Xenogears/build-sector.cpp
@@ -0,0 +1,14 @@
+#include <stdio.h>
+#include "yazedc.h"
+
+int main(void) {
+ unsigned char datas[2352];
+
+ fread(datas, 2352, 1, stdin);
+ minute = datas[12];
+ second = datas[13];
+ frame = datas[14];
+ fprintf(stderr, "Sector info: %2i:%02i:%04i\n", minute, second, frame);
+ do_encode_L2(datas, MODE_2_FORM_1, 0);
+ fwrite(datas, 2352, 1, stdout);
+}
diff --git a/Xenogears/compil-2.lex b/Xenogears/compil-2.lex
new file mode 100644
index 0000000..805a964
--- /dev/null
+++ b/Xenogears/compil-2.lex
@@ -0,0 +1,254 @@
+ /* In text block */
+%s I
+ /* Outside of text block */
+%s O
+ /* Waiting for Width argument */
+%s W
+ /* Waiting for OpCode arguments */
+%s Op
+
+ int num_blocks = 0;
+ int num_lines = 0;
+ int cur_num_lines = 0;
+ int cur_num_block = 0;
+ int line_width = 0;
+ int max_line_width = 0;
+ int block_lines = 0;
+ int block_width = 0;
+ int errstate = 0;
+ void yputc(int c, int a);
+
+%%
+
+<INITIAL>"<Blocks:"\ *[[:digit:]]+">"\n {
+ int i;
+ char zeros[4] = {0, 0, 0, 0};
+ num_blocks = atoi(yytext + 8);
+ fprintf(stderr, "Number of blocks: %i\n", num_blocks);
+
+ num_lines = 2;
+
+ BEGIN(O);
+ }
+
+<INITIAL>.* {
+ fprintf(stderr, "Invalid file, must begin with <Blocks: XX>\n");
+ errstate = 1;
+ num_lines = 2;
+ num_blocks = 9999;
+ }
+
+<O>"<Text_block lines:"\ *[[:digit:]]+\ + {
+ if (cur_num_block >= num_blocks) {
+ fprintf(stderr, "Error: too much blocks at line %i\n", num_lines);
+ errstate = 1;
+ }
+ block_lines = atoi(yytext + 18);
+ BEGIN(W);
+ }
+
+<W>"width:"\ *[[:digit:]]+">\n" {
+ block_width = atoi(yytext + 6);
+ fprintf(stderr, "Begin of block %i at line %i -- lines = %i, width = %i\n", cur_num_block, num_lines, block_lines, block_width);
+ num_lines++;
+ line_width = 0;
+ max_line_width = 0;
+ cur_num_lines = 1;
+ BEGIN(I);
+ }
+
+<W>.* {
+ fprintf(stderr, "Error: invalid arguments to command Text_block at line %i: '%s'\n", num_lines, yytext);
+ errstate = 1;
+ BEGIN(O);
+ }
+
+<I>\n {
+ if (line_width > block_width) {
+ fprintf(stderr, "Warning: line %i too long (%i > %i).\n", num_lines, line_width, block_width);
+ }
+ if (line_width > max_line_width)
+ max_line_width = line_width;
+ line_width = 0;
+ num_lines++;
+ cur_num_lines++;
+ if (cur_num_lines > block_lines) {
+ fprintf(stderr, "Warning: too much lines for text block %i at line %i (%i > %i)\n", cur_num_block, num_lines, cur_num_lines, block_lines);
+ }
+ putc('\n', yyout);
+ }
+
+<I>"<New>\n" {
+ if (line_width > block_width) {
+ fprintf(stderr, "Warning: line %i too long (%i > %i).\n", num_lines, line_width, block_width);
+ }
+ if (line_width > max_line_width)
+ max_line_width = line_width;
+ line_width = 0;
+ num_lines++;
+ cur_num_lines = 1;
+ putc('\n', yyout);
+ }
+
+<I>"<Wait>\n" {
+ if (line_width > block_width) {
+ fprintf(stderr, "Warning: line %i too long (%i > %i).\n", num_lines, line_width, block_width);
+ }
+ if (line_width > max_line_width)
+ max_line_width = line_width;
+ line_width = 0;
+ num_lines++;
+ cur_num_lines = 1;
+ putc('\n', yyout);
+ }
+
+<I>"<Wait>" {
+ cur_num_lines = 1;
+ }
+
+<I>"<Delay"\ +[[:digit:]]+">" {
+ int d = atoi(yytext + 7);
+ if (d > 255) {
+ fprintf(stderr, "Error: delay too important: %i\n", d);
+ errstate = 1;
+ }
+ }
+
+<I>"<Gear"\ +[[:digit:]]+">" {
+ int d = atoi(yytext + 5);
+ if (d > 255) {
+ fprintf(stderr, "Error: gear number too important: %i\n", d);
+ errstate = 1;
+ } else {
+ putc(0xf, yyout);
+ putc(5, yyout);
+ putc(d, yyout);
+ line_width += 16;
+ }
+ }
+
+<I>"<Opcode"\ +/[[:digit:]]+\ +[[:digit:]]+">" {
+ BEGIN(Op);
+ }
+
+<Op>[[:digit:]]+\ +[[:digit:]]+">" {
+ int o1, o2;
+ o1 = atoi(yytext);
+ o2 = atoi(yytext + (o1 < 10 ? 2 : o1 < 100 ? 3 : 4));
+ BEGIN(I);
+ }
+
+<Op>[^<]*">" {
+ yytext[strlen(yytext - 1)] = 0;
+ fprintf(stderr, "Error: invalid OpCode '%s'\n", yytext);
+ errstate = 1;
+ BEGIN(I);
+ }
+
+<I>"<"[[:digit:]]">" unput(*(yytext + 1));
+<I>"<".">" unput(*(yytext + 1));
+<I>"<..>" unput('.'); unput('.');
+<I>"<...>" unput('.'); unput('.'); unput('.');
+
+<I>"<Extra1"\ +[[:digit:]]+">" {
+ int d = atoi(yytext + 7);
+ if (d > 255) {
+ fprintf(stderr, "Error: Extra1 number too important: %i\n", d);
+ errstate = 1;
+ } else {
+ putc(0xfe, yyout);
+ putc(d, yyout);
+ }
+ }
+
+<I>"<Extra2"\ +[[:digit:]]+">" {
+ int d = atoi(yytext + 7);
+ if (d > 255) {
+ fprintf(stderr, "Error: Extra2 number too important: %i\n", d);
+ errstate = 1;
+ } else {
+ putc(0xff, yyout);
+ putc(d, yyout);
+ }
+ }
+
+<I>"<Bare"\ +[[:xdigit:]]{1,2}">" {
+ char str[5] = {'0', 'x', 0, 0, 0};
+ int d;
+ for (yytext += 6; *yytext == ' '; yytext++);
+ str[2] = *(yytext++);
+ str[3] = *(yytext++);
+ sscanf(str, "%i", &d);
+ if (d > 255) {
+ fprintf(stderr, "Error: Bare number too important: %i\n", d);
+ errstate = 1;
+ } else {
+ putc(d, yyout);
+ }
+ }
+
+<I>"<oe>" unput('e'); unput('o');
+<I>"<ae>" unput('e'); unput('a');
+
+<I>"\n<End_of_block>" {
+ if (line_width > max_line_width)
+ max_line_width = line_width;
+ if (max_line_width < block_width)
+ fprintf(stderr, "Warning: block %i too large (%i < %i)\n", cur_num_block, max_line_width, block_width);
+ num_lines++;
+ cur_num_block++;
+ putc('\n', yyout);
+ putc('\n', yyout);
+ BEGIN(O);
+ }
+
+<I>"<"[^\>\n]*">" {
+ yytext[strlen(yytext) - 1] = 0;
+ fprintf(stderr, "Error: Invalid command at line %i: '%s'\n", num_lines, yytext + 1);
+ errstate = 1;
+ }
+
+<O>\n num_lines++;
+<O>. /* Eat up comments */
+
+<I>. {
+ putc(*yytext, yyout);
+ }
+
+. {
+ fprintf(stderr, "Hu uh, something's wrong at line %i...\n", num_lines);
+ }
+
+%%
+
+int yywrap(void) {
+ if (cur_num_block < num_blocks) {
+ fprintf(stderr, "Warning: Too few blocks at end of file.\n");
+ }
+ exit(errstate ? -1 : 0);
+}
+
+int main(int argc, char ** argv) {
+ if ((argc < 2) || (argc > 3)) {
+ fprintf(stderr, "Usage: %s <output> [input]\n", argv[0]);
+ exit(-1);
+ }
+ if (!(yyout = fopen(argv[1], "wb"))) {
+ fprintf(stderr, "Error: can't open file %s\n", argv[1]);
+ exit(-1);
+ }
+ if (argc == 3) {
+ if (!(yyin = fopen(argv[2], "rb"))) {
+ fprintf(stderr, "Error: can't open file %s\n", argv[2]);
+ exit(-1);
+ }
+ }
+ fprintf(stderr, "Creating file %s\n", argv[1]);
+ yylex();
+ exit(errstate ? -1 : 0);
+}
+
+void yputc(int c, int a) {
+ line_width += a;
+ putc(c, yyout);
+}
diff --git a/Xenogears/compil.lex b/Xenogears/compil.lex
new file mode 100644
index 0000000..f6ceda8
--- /dev/null
+++ b/Xenogears/compil.lex
@@ -0,0 +1,383 @@
+ #include <string.h>
+ /* In text block */
+%s I
+ /* Outside of text block */
+%s O
+ /* Waiting for Width argument */
+%s W
+ /* Waiting for OpCode arguments */
+%s Op
+
+ int num_blocks = 0;
+ int num_lines = 0;
+ int cur_num_lines = 0;
+ int cur_num_block = 0;
+ int line_width = 0;
+ int max_line_width = 0;
+ int block_lines = 0;
+ int block_width = 0;
+ int errstate = 0;
+ void yputc(int c, int a);
+ void unputs(char *);
+
+%%
+
+<INITIAL>"<Blocks:"\ *[[:digit:]]+">"\n {
+ int i;
+ char zeros[4] = {0, 0, 0, 0};
+ num_blocks = atoi(yytext + 8);
+ fprintf(stderr, "Number of blocks: %i\n", num_blocks);
+ num_blocks--;
+ fwrite(&num_blocks, 4, 1, yyout);
+ num_blocks++;
+
+ for (i = 0; i < num_blocks; i++) {
+ fwrite(zeros, 4, 1, yyout);
+ }
+
+ num_lines = 2;
+
+ BEGIN(O);
+ }
+
+<INITIAL>.* {
+ fprintf(stderr, "Invalid file, must begin with <Blocks: XX>\n");
+ errstate = 1;
+ num_lines = 2;
+ num_blocks = 9999;
+ }
+
+<O>"<Text_block lines:"\ *[[:digit:]]+\ + {
+ if (cur_num_block >= num_blocks) {
+ fprintf(stderr, "Error: too much blocks at line %i\n", num_lines);
+ errstate = 1;
+ }
+ block_lines = atoi(yytext + 18);
+ BEGIN(W);
+ }
+
+<W>"width:"\ *[[:digit:]]+">\n" {
+ block_width = atoi(yytext + 6);
+ fprintf(stderr, "Begin of block %i at line %i -- lines = %i, width = %i\n", cur_num_block, num_lines, block_lines, block_width);
+ num_lines++;
+ line_width = 0;
+ max_line_width = 0;
+ cur_num_lines = 1;
+ if (num_blocks != 9999) {
+ long p = ftell(yyout);
+ fseek(yyout, 4 + cur_num_block * 2, SEEK_SET);
+ fwrite(&p, 2, 1, yyout);
+ fseek(yyout, (num_blocks - 1) * 2, SEEK_CUR);
+ putc(block_width, yyout);
+ putc(block_lines, yyout);
+ fseek(yyout, 0, SEEK_END);
+ }
+ BEGIN(I);
+ }
+
+<W>.* {
+ fprintf(stderr, "Error: invalid arguments to command Text_block at line %i: '%s'\n", num_lines, yytext);
+ errstate = 1;
+ BEGIN(O);
+ }
+
+<I>"\n" {
+ if (line_width > block_width) {
+ fprintf(stderr, "Warning: line %i too long (%i > %i).\n", num_lines, line_width, block_width);
+ }
+ if (line_width > max_line_width)
+ max_line_width = line_width;
+ line_width = 0;
+ num_lines++;
+ cur_num_lines++;
+ if (cur_num_lines > block_lines) {
+ fprintf(stderr, "Warning: too much lines for text block %i at line %i (%i > %i)\n", cur_num_block, num_lines, cur_num_lines, block_lines);
+ }
+ putc(1, yyout);
+ }
+
+<I>"<New>\n" {
+ if (line_width > block_width) {
+ fprintf(stderr, "Warning: line %i too long (%i > %i).\n", num_lines, line_width, block_width);
+ }
+ if (line_width > max_line_width)
+ max_line_width = line_width;
+ line_width = 0;
+ num_lines++;
+ cur_num_lines = 1;
+ putc(2, yyout);
+ }
+
+<I>"<Wait>\n" {
+ if (line_width > block_width) {
+ fprintf(stderr, "Warning: line %i too long (%i > %i).\n", num_lines, line_width, block_width);
+ }
+ if (line_width > max_line_width)
+ max_line_width = line_width;
+ line_width = 0;
+ num_lines++;
+ cur_num_lines = 1;
+ putc(1, yyout);
+ putc(3, yyout);
+ }
+
+<I>"<Wait>" {
+ cur_num_lines = 1;
+ putc(3, yyout);
+ }
+
+<I>"<Delay"\ +[[:digit:]]+">" {
+ int d = atoi(yytext + 7);
+ if (d > 255) {
+ fprintf(stderr, "Error: delay too important: %i\n", d);
+ errstate = 1;
+ } else {
+ putc(0xf, yyout);
+ putc(0, yyout);
+ putc(d, yyout);
+ }
+ }
+
+<I>"<Gear"\ +[[:digit:]]+">" {
+ int d = atoi(yytext + 5);
+ if (d > 255) {
+ fprintf(stderr, "Error: gear number too important: %i\n", d);
+ errstate = 1;
+ } else {
+ putc(0xf, yyout);
+ putc(5, yyout);
+ putc(d, yyout);
+ line_width += 16;
+ }
+ }
+
+<I>"<Opcode"\ +/[[:digit:]]+\ +[[:digit:]]+">" {
+ BEGIN(Op);
+ }
+
+<Op>[[:digit:]]+\ +[[:digit:]]+">" {
+ int o1, o2;
+ o1 = atoi(yytext);
+ o2 = atoi(yytext + (o1 < 10 ? 2 : o1 < 100 ? 3 : 4));
+ putc(0xf, yyout);
+ putc(o1, yyout);
+ putc(o2, yyout);
+ BEGIN(I);
+ }
+
+<Op>[^<]*">" {
+ yytext[strlen(yytext - 1)] = 0;
+ fprintf(stderr, "Error: invalid OpCode '%s'\n", yytext);
+ errstate = 1;
+ BEGIN(I);
+ }
+
+<I>" " yputc(0x10, 2);
+<I>"+" yputc(0x11, 2);
+<I>"," yputc(0x12, 2);
+<I>"-" yputc(0x13, 2);
+<I>"." yputc(0x14, 2);
+<I>"/" yputc(0x15, 2);
+<I>[[:digit:]] yputc(*yytext - 0x1a, 2);
+<I>[[:upper:]] yputc(*yytext - 0x21, 2);
+<I>"[" yputc(0x3a, 2);
+<I>"]" yputc(0x3b, 2);
+<I>"=" yputc(0x3c, 2);
+<I>[[:lower:]] yputc(*yytext - 0x24, 2);
+<I>"!" yputc(0x57, 2);
+<I>"\"" yputc(0x58, 2);
+<I>"#" yputc(0x59, 2);
+<I>"%" yputc(0x5a, 2);
+<I>"&" yputc(0x5b, 2);
+<I>"'" yputc(0x5c, 2);
+<I>"(" yputc(0x5d, 2);
+<I>")" yputc(0x5e, 2);
+<I>":" yputc(0x5f, 2);
+<I>"?" yputc(0x60, 2);
+<I>"<"[[:digit:]]">" yputc(*(yytext + 1) + 0x31, 3);
+<I>"<%>" yputc(0x6b, 3);
+<I>"<&>" yputc(0x6c, 3);
+<I>"*" yputc(0x6d, 3);
+<I>"<C>" yputc(0x6e, 3);
+<I>"<S>" yputc(0x6f, 3);
+<I>"<T>" yputc(0x70, 3);
+<I>"<*>" yputc(0x71, 3);
+<I>"<R>" yputc(0x72, 3);
+<I>"<L>" yputc(0x73, 3);
+<I>"<U>" yputc(0x74, 3);
+<I>"<D>" yputc(0x75, 3);
+<I>"<.>" yputc(0x76, 3);
+<I>"<:>" yputc(0x77, 3);
+<I>"</>" yputc(0x79, 3);
+<I>"<..>" yputc(0x7a, 3);
+<I>"<`>" yputc(0x7b, 3);
+<I>"<+>" yputc(0x7d, 3);
+<I>"<->" yputc(0x7e, 3);
+<I>"<X>" yputc(0x7f, 3);
+<I>"<[>" yputc(0x80, 3);
+<I>"<]>" yputc(0x81, 3);
+<I>"<(>" yputc(0x84, 3);
+<I>"<)>" yputc(0x85, 3);
+<I>"<#>" yputc(0x86, 3);
+<I>"`" yputc(0x87, 3);
+<I>"°" yputc(0x88, 3);
+<I>"<=>" yputc(0x89, 3);
+<I>"<?>" yputc(0x8a, 3);
+<I>"<!>" yputc(0x8b, 3);
+<I>"_" yputc(0x8c, 3);
+<I>"~" yputc(0x8d, 3);
+<I>"<...>" yputc(0x8e, 3);
+<I>"<'>" yputc(0x8f, 3);
+
+<I>"<Extra1"\ +[[:digit:]]+">" {
+ int d = atoi(yytext + 7);
+ if (d > 255) {
+ fprintf(stderr, "Error: Extra1 number too important: %i\n", d);
+ errstate = 1;
+ } else {
+ putc(0xfe, yyout);
+ putc(d, yyout);
+ }
+ }
+
+<I>"<Extra2"\ +[[:digit:]]+">" {
+ int d = atoi(yytext + 7);
+ if (d > 255) {
+ fprintf(stderr, "Error: Extra2 number too important: %i\n", d);
+ errstate = 1;
+ } else {
+ putc(0xff, yyout);
+ putc(d, yyout);
+ }
+ }
+
+<I>"<Bare"\ +[[:xdigit:]]{1,2}">" {
+ char str[5] = {'0', 'x', 0, 0, 0};
+ int d;
+ for (yytext += 6; *yytext == ' '; yytext++);
+ str[2] = *(yytext++);
+ str[3] = *(yytext++);
+ sscanf(str, "%i", &d);
+ if (d > 255) {
+ fprintf(stderr, "Error: Bare number too important: %i\n", d);
+ errstate = 1;
+ } else {
+ putc(d, yyout);
+ }
+ }
+
+<I>à|â|ä unput('a');
+<I>é|è|ê|ë unput('e');
+<I>î|ï unput('i');
+<I>ô|ö unput('o');
+<I>û|ü|ù unput('u');
+<I>ç unput('c');
+<I>"<oe>" unput('e'); unput('o');
+<I>"<ae>" unput('e'); unput('a');
+
+<I>"<Fei>" unputs("<Gear 00>");
+<I>"<Elly>" unputs("<Gear 01>");
+<I>"<Citan>" unputs("<Gear 02>");
+<I>"<Bart>" unputs("<Gear 03>");
+<I>"<Billy>" unputs("<Gear 04>");
+<I>"<Rico>" unputs("<Gear 05>");
+<I>"<Emeralda>" unputs("<Gear 06>");
+<I>"<Chu-Chu>" unputs("<Gear 07>");
+<I>"<Maria>" unputs("<Gear 08>");
+<I>"<Citan-2>" unputs("<Gear 09>");
+<I>"<Emeralda-2>" unputs("<Gear 10>");
+<I>"<Weltall>" unputs("<Gear 11>");
+<I>"<Waltall-2>" unputs("<Gear 12>");
+<I>"<Vierge>" unputs("<Gear 13>");
+<I>"<Heimdal>" unputs("<Gear 14>");
+<I>"<Brigandier>" unputs("<Gear 15>");
+<I>"<Renmazuo>" unputs("<Gear 16>");
+<I>"<Stier>" unputs("<Gear 17>");
+<I>"<BigChu-chu>" unputs("<Gear 18>");
+<I>"<Seibzehn>" unputs("<Gear 19>");
+<I>"<Crescens>" unputs("<Gear 20>");
+<I>"<Regurus>" unputs("<Gear 21>");
+<I>"<Fenrir>" unputs("<Gear 22>");
+<I>"<Andvari>" unputs("<Gear 23>");
+<I>"<Renmazuo>" unputs("<Gear 24>");
+<I>"<Stier-2>" unputs("<Gear 25>");
+<I>"<Xenogears>" unputs("<Gear 26>");
+<I>"<BARTHOS>" unputs("<Gear 27>");
+<I>"<Yggdra>" unputs("<Gear 29>");
+<I>"<Perso1>" unputs("<Gear 128>");
+<I>"<Perso2>" unputs("<Gear 129>");
+<I>"<Perso3>" unputs("<Gear 130>");
+
+
+<I>"\n<End_of_block>" {
+ if (line_width > max_line_width)
+ max_line_width = line_width;
+ if (max_line_width < block_width)
+ fprintf(stderr, "Warning: block %i too large (%i < %i)\n", cur_num_block, max_line_width, block_width);
+ if (line_width > block_width)
+ fprintf(stderr, "Warning: line %i too long (%i > %i).\n", num_lines, line_width, block_width);
+ num_lines++;
+ cur_num_block++;
+ putc(0, yyout);
+ BEGIN(O);
+ }
+
+<I>"<"[^\>\n]*">" {
+ yytext[strlen(yytext) - 1] = 0;
+ fprintf(stderr, "Error: Invalid command at line %i: '%s'\n", num_lines, yytext + 1);
+ errstate = 1;
+ }
+
+<O>\n num_lines++;
+<O>. /* Eat up comments */
+
+<I>. {
+ fprintf(stderr, "Invalid character at line %i: '%c'\n", num_lines, *yytext);
+ errstate = 1;
+ }
+
+. {
+ fprintf(stderr, "Hu uh, something's wrong at line %i...\n", num_lines);
+ }
+
+%%
+
+int yywrap(void) {
+ if (cur_num_block < num_blocks) {
+ fprintf(stderr, "Warning: Too few blocks at end of file.\n");
+ }
+ exit(errstate ? -1 : 0);
+}
+
+int main(int argc, char ** argv) {
+ if ((argc < 2) || (argc > 3)) {
+ fprintf(stderr, "Usage: %s <output> [input]\n", argv[0]);
+ exit(-1);
+ }
+ if (!(yyout = fopen(argv[1], "wb"))) {
+ fprintf(stderr, "Error: can't open file %s\n", argv[1]);
+ exit(-1);
+ }
+ if (argc == 3) {
+ if (!(yyin = fopen(argv[2], "rb"))) {
+ fprintf(stderr, "Error: can't open file %s\n", argv[2]);
+ exit(-1);
+ }
+ }
+ fprintf(stderr, "Creating file %s\n", argv[1]);
+ yylex();
+ exit(errstate ? -1 : 0);
+}
+
+void yputc(int c, int a) {
+ line_width += a;
+ putc(c, yyout);
+}
+
+void unputs(char * s) {
+ int l = strlen(s), i;
+
+ for (i = l - 1; i >= 0; i--) {
+ unput(s[i]);
+ }
+}
diff --git a/Xenogears/main_dump.cpp b/Xenogears/main_dump.cpp
new file mode 100644
index 0000000..2f79a86
--- /dev/null
+++ b/Xenogears/main_dump.cpp
@@ -0,0 +1,291 @@
+/*
+ * Xenogears extractor by Nicolas "Pixel" Noble (nicolas@nobis-crew.org)
+ * Highly based upon Yazoo's Chrono Cross CD extractor
+ *
+ * ******** Original disclaimer by Yazoo ********
+ *
+ * Chrono Cross CD extractor Copyright 2000-2001 by Yazoo (hamm@efrei.fr) Revision 0.1b ANSI C
+ *
+ *
+ * Features:
+ *
+ * Dump the complete content of Chrono Chross CD1/CD2 US and Japanese version It requires a iso
+ * named Chrono1.iso in the same directory
+ *
+ * Todo list:
+ *
+ * Find a way to locate end of the last file Better support for CD2 Dump in subdirectory according
+ * to CD1/CD2 repartition Recompilation in Visual C++ 6 for disk speed optimisation Source comment
+ * and reorganisation Log feature (Optional since you can redirect output with > ) Progression
+ * indicator Better detection of the ISO with error control Major code optimisation Integration in
+ * main Chrono Cross Hacking tool
+ *
+ * ******** End of original disclaimer by Yazoo ********
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "fileutils.h"
+#include "cdutils.h"
+#include "generic.h"
+
+unsigned int tourne = 0;
+
+struct t_index_tab {
+ unsigned long address;
+ long size;
+ long type;
+ long index;
+};
+
+struct t_sequence {
+ unsigned int n;
+ unsigned int sum;
+ char *prefix;
+ char *name;
+ int type;
+};
+
+char *title, *iso_filename, *prefix;
+unsigned long iso_size;
+unsigned int nb_records, nb_seqs = 0;
+struct t_sequence sequences[1000];
+
+long check_iso(int f_iso);
+void read_files(int f_iso);
+void file_dump(int f_iso, unsigned long debut, unsigned long taille, long num, int seq);
+int process_def_file(int f_def);
+
+unsigned char user_data[2352];
+
+int main(int argc, char **argv)
+{
+ int f_def, f_iso;
+
+ verbosity = 3;
+
+ fprintf(stderr,
+"Xenogears File Extractor by Nicolas \"Pixel\" Noble\n"
+"Highly based upon the Chrono Cross File Extractor By Yazoo\n\n");
+
+ if (argc != 3) {
+ fprintf(stderr, "Usage: %s <definition_file.sqr> <iso_file_name>\nSee readme.txt for details\n",
+ argv[0]);
+ exit(-1);
+ }
+
+ printm(M_STATUS, "Processing file %s...\n", argv[1]);
+
+ if ((f_def = open(argv[1], O_RDONLY)) < 0) {
+ printm(M_ERROR, "Unable to open the definition file \"%s\"...\n", argv[1]);
+ exit(-1);
+ }
+
+ if (process_def_file(f_def)) {
+ close(f_def);
+ printm(M_ERROR, "Unable to process the definition file \"%s\"...\n", argv[1]);
+ exit(-1);
+ }
+
+ iso_filename = argv[2];
+
+ printm(M_STATUS, "Begin processing iso file.\n");
+ if ((f_iso = open(iso_filename, O_RDONLY)) < 0) {
+ printm(M_ERROR, "Unable to open the iso file \"%s\"...\n", iso_filename);
+ exit(-1);
+ }
+
+ if (check_iso(f_iso)) {
+ printm(M_ERROR, "Invalid iso file for %s\n", title);
+ printm(M_ERROR, "===> Make sure you are using a Genuine iso file.\n");
+ } else {
+ printm(M_INFO, "Genuine %s iso detected.\n", title);
+ }
+ printm(M_STATUS, "Entering files read sequence\n");
+ read_files(f_iso);
+ close(f_iso);
+ exit(0);
+}
+
+/*
+ * Ugly but working... for now
+ */
+int process_def_file(int h_f_def)
+{
+ char t[1024], *p;
+ unsigned int n, sum = 0;
+ FILE * f_def = fdopen(h_f_def, "r");
+
+ if ((p = strchr(fgets(t, 1024, f_def), '\n')) == NULL)
+ return 1;
+ *p = 0;
+ printm(M_INFO, "Read title: %s\n", t);
+ title = strdup(t);
+
+ if (fscanf(f_def, "%lu\n", &iso_size) != 1)
+ return 1;
+ printm(M_INFO, "Read iso size: %lu bytes\n", iso_size);
+
+ if ((p = strchr(fgets(t, 1024, f_def), '\n')) == NULL)
+ return 1;
+ *p = 0;
+ printm(M_INFO, "Read global directory prefix: %s\n", t);
+ prefix = strdup(t);
+
+ if (fscanf(f_def, "%u\n", &nb_records) != 1)
+ return 1;
+ printm(M_INFO, "Read total of records: %u\n", nb_records);
+
+ while (1) {
+ if (fscanf(f_def, "%u\n", &n) != 1)
+ return 1;
+ if (!n) {
+ if (sum == nb_records) {
+ printm(M_INFO, "Definition file seems coherent\n");
+ return 0;
+ } else {
+ printm(M_ERROR, "Definition file incoherent\n");
+ return 1;
+ }
+ }
+ sum += n;
+ sequences[nb_seqs].n = n;
+ sequences[nb_seqs].sum = sum;
+ if ((p = strchr(fgets(t, 1024, f_def), '\n')) == NULL)
+ return 1;
+ *p = 0;
+ sequences[nb_seqs].prefix = strdup(t);
+ if (fscanf(f_def, "%u\n", &n) != 1)
+ return 1;
+ sequences[nb_seqs].type = n;
+ if ((p = strchr(fgets(t, 1024, f_def), '\n')) == NULL)
+ return 1;
+ *p = 0;
+ sequences[nb_seqs].name = strdup(t);
+ printm(M_INFO, "Read definition of sequence %i:\n===> %5i (sum = %5i) chunks of %s (%s)\n",
+ nb_seqs, n, sum, t, sequences[nb_seqs].prefix);
+ nb_seqs++;
+ }
+}
+
+long check_iso(int f_iso)
+{
+ unsigned long length;
+
+ length = filesize(f_iso);
+ printm(M_INFO, "Filesize of iso file %s is %ld bytes\n", iso_filename, length);
+ if (length != iso_size) {
+ return 1;
+ }
+ return 0;
+}
+
+void read_files(int f_iso)
+{
+ t_index_tab index_tab[10000];
+ unsigned char t[8];
+ unsigned long i;
+ unsigned long j;
+ unsigned int seq = 0;
+ unsigned long indexer;
+ struct t_index_tab *p = (struct t_index_tab *) t;
+
+ unsigned char fat[32768];
+
+#define INDEXPOS 24
+
+ sector_seek(f_iso, INDEXPOS);
+ for (i = INDEXPOS; i < (INDEXPOS + 16); i++) {
+ printm(M_INFO, "Reading fat sector %lu\n", i);
+ read_sector(f_iso, &fat[2048 * (i - INDEXPOS)], MODE_2_FORM_1);
+ }
+
+ indexer = 0;
+ for (j = 0; j < 32768; j = j + 7) {
+ t[0] = 0;
+ bcopy((char *) &fat[j], (char *) t + 1, 7);
+ p->address >>= 8;
+ index_tab[indexer] = *p;
+ if (p->size > 0 && p->address != 0) {
+ index_tab[indexer].index = j / 7;
+ printm(M_INFO, "Found a quite valid index: number %4lu, address %6lu, size %3li\n",
+ indexer, index_tab[indexer].address, index_tab[indexer].size);
+ indexer++;
+ if (indexer == nb_records)
+ break;
+ } else {
+ printm(M_WARNING, "Ignored invalid index chunk number %4lu (size = %lu) (%02x %02x %02x %02x %02x %02x %02x)\n",
+ j / 7, -index_tab[indexer].size, t[0], t[1], t[2], t[4], t[5], t[6], t[7]);
+ }
+ }
+ printm(M_STATUS, "Index file generation complete.\n\n");
+
+ for (i = 0; i < nb_records; i++) {
+ if (sequences[seq].sum == i)
+ seq++;
+ index_tab[i].type = sequences[seq].type;
+ if (sequences[seq].type == 0) {
+ printm(M_INFO, "%6lu (%10lu): ignored\n", index_tab[i].address, index_tab[i].size);
+ } else {
+ printm(M_INFO, "%6lu (%10lu): ", index_tab[i].address, index_tab[i].size);
+ file_dump(f_iso, index_tab[i].address, index_tab[i].size, i, seq);
+ if (verbosity >= M_INFO) {
+ fprintf(stderr, "\n");
+ }
+ }
+ }
+ fprintf(stderr, "\n");
+}
+
+void file_dump(int f_iso, unsigned long debut, unsigned long taille, long num, int seq)
+{
+ long i;
+ long nbsects;
+ char nom[1000] = "";
+ char *extention = ".out";
+ char nom_t[1000] = "";
+ int f_out;
+ char type = sequences[seq].type;
+ char ptitbidule[] = "-\\|/";
+
+ sprintf(nom_t, "%ld", num);
+
+ strcat(nom, "./");
+
+ strcat(nom, prefix);
+ strcat(nom, "/");
+ MKDIR(nom);
+
+ strcat(nom, sequences[seq].prefix);
+ strcat(nom, "/");
+ MKDIR(nom);
+
+ if (num < 10)
+ strcat(nom, "0");
+ if (num < 100)
+ strcat(nom, "0");
+ if (num < 1000)
+ strcat(nom, "0");
+ strcat(nom, nom_t);
+
+ strcat(nom, extention);
+ f_out = open(nom, O_WRONLY | O_CREAT | O_TRUNC, 00644);
+ nbsects = taille / sec_sizes[type];
+ if (taille % sec_sizes[type])
+ nbsects++;
+ sector_seek(f_iso, debut);
+ for (i = 0; i < nbsects; i++) {
+ if (verbosity < M_INFO)
+ fprintf(stderr, " (%c)\010\010\010\010\010", ptitbidule[((tourne++) >> 8) % 4]);
+ read_sector(f_iso, user_data, type);
+ if (i != (nbsects - 1)) {
+ write(f_out, user_data, sec_sizes[type]);
+ } else {
+ write(f_out, user_data, taille % sec_sizes[type] ? taille % sec_sizes[type] : sec_sizes[type]);
+ }
+ }
+ close(f_out);
+ fprintf(stderr, " (*) Dumped file number %4ld - type \"%s\" \r", num, sequences[seq].name);
+}
diff --git a/Xenogears/map2sqr b/Xenogears/map2sqr
new file mode 100755
index 0000000..4621d54
--- /dev/null
+++ b/Xenogears/map2sqr
@@ -0,0 +1,34 @@
+#!/usr/bin/awk -f
+BEGIN {
+ ol = -1;
+}
+
+NR <= 4 {
+ print $0;
+}
+
+NR > 4 {
+ f = $1;
+ l = $2;
+ c = l - f + 1;
+ if ((ol + 1) != f) {
+ print "You blew it @ line", NR > "/dev/stderr"
+ exit -1;
+ }
+ ol = l;
+ print c;
+
+ d = $3;
+ print d;
+ d = $4;
+ print d;
+ for (i = 5; i < NR; i++) {
+ $(i - 4) = $i;
+ }
+ NF -= 4;
+ print $0;
+}
+
+END {
+ print 0;
+}
diff --git a/Xenogears/reinsert.cpp b/Xenogears/reinsert.cpp
new file mode 100644
index 0000000..e58b871
--- /dev/null
+++ b/Xenogears/reinsert.cpp
@@ -0,0 +1,305 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "fileutils.h"
+#include "cdutils.h"
+#include "generic.h"
+
+unsigned int tourne = 0;
+
+struct t_index_tab {
+ unsigned long address;
+ long size;
+ long type;
+ long index;
+};
+
+struct t_sequence {
+ unsigned int n;
+ unsigned int sum;
+ char *prefix;
+ char *name;
+ int type;
+};
+
+char *title, *iso_filename, *tbl_filename, *prefix, *in_filename;
+unsigned long iso_size;
+unsigned int nb_records, nb_seqs = 0;
+struct t_sequence sequences[1000];
+
+int slus_index = -1, force = 0;
+
+long check_iso(int f_iso);
+void write_files(int f_iso_r, int f_iso_w, int f_in, int fileindex);
+int process_def_file(int f_def);
+
+unsigned char user_data[2352];
+
+void usage(char ** argv) {
+ fprintf(stderr, "Usage: %s <definition_file.sqr> <iso_file_name> <file_index> <filename> [-f]\nSee readme.txt for details\n",
+ argv[0]);
+ exit(-1);
+}
+
+int main(int argc, char **argv)
+{
+ int f_def, f_iso_r, f_iso_w, f_in;
+ int fileindex;
+
+ verbosity = 1;
+
+ fprintf(stderr, "Xenogears File Insertor by Nicolas \"Pixel\" Noble\n\n");
+
+ if ((argc != 5) && (argc != 6)) {
+ usage(argv);
+ }
+
+ if (argc == 6) {
+ if (strcmp(argv[5], "-f")) {
+ usage(argv);
+ } else {
+ force = 1;
+ }
+ }
+
+ printm(M_STATUS, "Processing file %s...\n", argv[1]);
+
+ if ((f_def = open(argv[1], O_RDONLY)) < 0) {
+ printm(M_ERROR, "Unable to open the definition file \"%s\"...\n", argv[1]);
+ exit(-1);
+ }
+
+ if (process_def_file(f_def)) {
+ close(f_def);
+ printm(M_ERROR, "Unable to process the definition file \"%s\"...\n", argv[1]);
+ exit(-1);
+ }
+
+ iso_filename = argv[2];
+
+ printm(M_STATUS, "Begin processing iso file.\n");
+ if ((f_iso_r = open(iso_filename, O_RDONLY)) < 0) {
+ printm(M_ERROR, "Unable to open the iso file \"%s\"...\n", iso_filename);
+ exit(-1);
+ }
+
+ if ((f_iso_w = open(iso_filename, O_WRONLY)) < 0) {
+ printm(M_ERROR, "Unable to open the iso file \"%s\"...\n", iso_filename);
+ exit(-1);
+ }
+
+ if (check_iso(f_iso_r)) {
+ printm(M_ERROR, "Invalid iso file for %s\n", title);
+ printm(M_ERROR, "===> Make sure you are using a Genuine iso file.\n");
+ } else {
+ printm(M_INFO, "Genuine %s iso detected.\n", title);
+ }
+
+ fileindex = atoi(argv[3]);
+ in_filename = argv[4];
+ if ((f_in = open(in_filename, O_RDONLY)) < 0) {
+ printm(M_ERROR, "Unable to open the file \"%s\"...\n", in_filename);
+ exit(-1);
+ }
+
+ printm(M_STATUS, "Entering files write sequence\n");
+ write_files(f_iso_r, f_iso_w, f_in, fileindex);
+ close(f_iso_r);
+ close(f_iso_w);
+ exit(0);
+}
+
+/*
+ * Ugly but working... for now
+ */
+int process_def_file(int h_f_def)
+{
+ char t[1024], *p;
+ unsigned int n, sum = 0;
+ FILE * f_def = fdopen(h_f_def, "r");
+
+ if ((p = strchr(fgets(t, 1024, f_def), '\n')) == NULL)
+ return 1;
+ *p = 0;
+ printm(M_INFO, "Read title: %s\n", t);
+ title = strdup(t);
+
+ if (fscanf(f_def, "%lu\n", &iso_size) != 1)
+ return 1;
+ printm(M_INFO, "Read iso size: %lu bytes\n", iso_size);
+
+ if ((p = strchr(fgets(t, 1024, f_def), '\n')) == NULL)
+ return 1;
+ *p = 0;
+ printm(M_INFO, "Read index table filename: %s\n", t);
+ tbl_filename = strdup(t);
+
+ if ((p = strchr(fgets(t, 1024, f_def), '\n')) == NULL)
+ return 1;
+ *p = 0;
+ printm(M_INFO, "Read global directory prefix: %s\n", t);
+ prefix = strdup(t);
+
+ if (fscanf(f_def, "%u\n", &nb_records) != 1)
+ return 1;
+ printm(M_INFO, "Read total of records: %u\n", nb_records);
+
+ while (1) {
+ if (fscanf(f_def, "%u\n", &n) != 1)
+ return 1;
+ if (!n) {
+ if (sum == nb_records) {
+ printm(M_INFO, "Definition file seems coherent\n");
+ return 0;
+ } else {
+ printm(M_ERROR, "Definition file incoherent\n");
+ return 1;
+ }
+ }
+ sum += n;
+ sequences[nb_seqs].n = n;
+ sequences[nb_seqs].sum = sum;
+ if ((p = strchr(fgets(t, 1024, f_def), '\n')) == NULL)
+ return 1;
+ *p = 0;
+ sequences[nb_seqs].prefix = strdup(t);
+ if (fscanf(f_def, "%u\n", &n) != 1)
+ return 1;
+ sequences[nb_seqs].type = n;
+ if ((p = strchr(fgets(t, 1024, f_def), '\n')) == NULL)
+ return 1;
+ *p = 0;
+ sequences[nb_seqs].name = strdup(t);
+ printm(M_INFO, "Read definition of sequence %i:\n===> %5i (sum = %5i) chunks of %s (%s)\n",
+ nb_seqs, n, sum, t, sequences[nb_seqs].prefix);
+ nb_seqs++;
+ }
+}
+
+long check_iso(int f_iso)
+{
+ unsigned long length;
+
+ length = filesize(f_iso);
+ printm(M_INFO, "Filesize of iso file %s is %ld bytes\n", iso_filename, length);
+ if (length != iso_size) {
+ return 1;
+ }
+ return 0;
+}
+
+#define INDEXPOS 24
+
+void rewrite_fat(int f_iso_r, int f_iso_w, unsigned char * new_fat) {
+ unsigned char old_fat[34816];
+ int i;
+
+ sector_seek(f_iso_w, INDEXPOS);
+ for (i = INDEXPOS; i < (INDEXPOS + 16); i++) {
+ printm(M_INFO, "Writing fat sector %lu\n", i);
+ write_sector(f_iso_r, f_iso_w, &new_fat[2048 * (i - INDEXPOS)], MODE_2_FORM_1);
+ }
+
+ sector_seek(f_iso_r, slus_index + 1);
+ for (i = slus_index + 1; i < (slus_index + 18); i++) {
+ printm(M_INFO, "Reading SLUS sector %lu\n", i);
+ read_sector(f_iso_r, &old_fat[2048 * (i - slus_index - 1)], MODE_2_FORM_1);
+ }
+
+ bcopy((char *) new_fat, (char *) old_fat + 4, 32768);
+ sector_seek(f_iso_w, slus_index + 1);
+ for (i = slus_index + 1; i < (slus_index + 18); i++) {
+ printm(M_INFO, "Writing SLUS sector %lu\n", i);
+ write_sector(f_iso_r, f_iso_w, &old_fat[2048 * (i - slus_index - 1)], MODE_2_FORM_1);
+ }
+}
+
+void write_files(int f_iso_r, int f_iso_w, int f_in, int fileindex)
+{
+ t_index_tab index_tab[10000];
+ unsigned char t[8];
+ unsigned long i;
+ unsigned long j;
+ unsigned int seq = 0;
+ unsigned long indexer;
+ struct t_index_tab *p = (struct t_index_tab *) t;
+
+ long old_file_size, new_file_size, old_nb_sects, new_nb_sects;
+ unsigned char fat[32768];
+
+ sector_seek(f_iso_r, INDEXPOS);
+ for (i = INDEXPOS; i < (INDEXPOS + 16); i++) {
+ printm(M_INFO, "Reading fat sector %lu\n", i);
+ read_sector(f_iso_r, &fat[2048 * (i - INDEXPOS)], MODE_2_FORM_1);
+ }
+
+ indexer = 0;
+ for (j = 0; j < 32768; j = j + 7) {
+ t[0] = 0;
+ bcopy((char *) &fat[j], (char *) t + 1, 7);
+ p->address >>= 8;
+ index_tab[indexer] = *p;
+ if (p->size > 0 && p->address != 0) {
+ index_tab[indexer].index = j / 7;
+ printm(M_INFO, "Found a quite valid index: number %4lu, address %6lu, size %3li\n",
+ indexer, index_tab[indexer].address, index_tab[indexer].size);
+ indexer++;
+ if (indexer == nb_records)
+ break;
+ } else {
+ printm(M_WARNING, "Ignored invalid index chunk number %4lu (size = %lu) (%02x %02x %02x %02x %02x %02x %02x)\n",
+ j / 7, -index_tab[indexer].size, t[0], t[1], t[2], t[4], t[5], t[6], t[7]);
+ }
+ }
+ printm(M_STATUS, "Index file generation complete.\n\n");
+
+ for (i = 0; i < nb_records; i++) {
+ if (sequences[seq].sum == i)
+ seq++;
+ index_tab[i].type = sequences[seq].type;
+ if (!strcmp(sequences[seq].prefix, "SLUS")) {
+ if (slus_index >= 0) {
+ printm(M_ERROR, "Two SLUS files defined\n");
+ exit(-1);
+ }
+ slus_index = index_tab[i].address;
+ }
+ }
+
+ if (slus_index < 0) {
+ printm(M_ERROR, "No SLUS file defined\n");
+ exit(-1);
+ }
+
+ printm(M_INFO, "SLUS file found at sector %6i\n", slus_index);
+
+ new_file_size = filesize(f_in);
+ old_file_size = index_tab[fileindex].size;
+
+ new_nb_sects = new_file_size / sec_sizes[index_tab[fileindex].type];
+ old_nb_sects = old_file_size / sec_sizes[index_tab[fileindex].type];
+
+ if (new_file_size % sec_sizes[index_tab[fileindex].type]) {
+ new_nb_sects++;
+ }
+
+ if (old_file_size % sec_sizes[index_tab[fileindex].type]) {
+ old_nb_sects++;
+ }
+
+ if (new_nb_sects > old_nb_sects) {
+ printm(M_ERROR, "New file too big.\n");
+ if (!force) {
+ exit(-1);
+ }
+ }
+
+ printm(M_INFO, "New file size: %12li, old file size: %12li\n", new_file_size, old_file_size);
+ printm(M_INFO, "New file ssize: %12li, old file ssize: %12li\n", new_nb_sects, old_nb_sects);
+
+ printm(M_INFO, "File address: %6i\n", index_tab[fileindex].address);
+
+ write_file(f_iso_r, f_iso_w, f_in, index_tab[fileindex].type, index_tab[fileindex].address);
+ *((long *)(&fat[index_tab[fileindex].index * 7 + 3])) = new_file_size;
+ rewrite_fat(f_iso_r, f_iso_w, fat);
+}
diff --git a/Xenogears/script-comp.cpp b/Xenogears/script-comp.cpp
new file mode 100644
index 0000000..96645df
--- /dev/null
+++ b/Xenogears/script-comp.cpp
@@ -0,0 +1,96 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "lz77.h"
+#include "fileutils.h"
+
+void process_one_file(int f, int d, int n) {
+ char nom_du_fichier[100];
+ char zeros[4] = {0, 0, 0, 0}, * datas;
+ long script_position, true_length, delta, data_length;
+ int f_part;
+
+ fprintf(stderr, " Copying header\n");
+
+ lseek(f, 0x14c, SEEK_SET);
+ read(f, &script_position, 4);
+ lseek(f, 0, SEEK_SET);
+ copy(f, d, script_position);
+
+ lseek(f, 0x150, SEEK_SET);
+ read(f, &script_position, 4);
+ lseek(f, script_position, SEEK_SET);
+
+ data_length = filesize(f) - script_position;
+
+ datas = (char *) malloc(data_length);
+ read(f, datas, data_length);
+
+ fprintf(stderr, " Processing script\n");
+ sprintf(nom_du_fichier, "xeno_d1/ROOMS/%04i/script.comp", n);
+
+ f_part = open(nom_du_fichier, O_RDONLY);
+ true_length = filesize(f_part);
+
+ script_position = lseek(d, 0, SEEK_CUR);
+ lseek(d, 0x14c, SEEK_SET);
+ write(d, &script_position, 4);
+ lseek(d, 0x128, SEEK_SET);
+ write(d, &true_length, 4);
+ lseek(d, 0, SEEK_END);
+
+ lz77_comp(f_part, d, &delta);
+
+ close(f_part);
+
+ script_position = lseek(d, 0, SEEK_CUR);
+ if ((true_length = (script_position & 3))) {
+ write(d, zeros, 4 - true_length);
+ }
+
+ fprintf(stderr, " Processing extra datas\n");
+ script_position = lseek(d, 0, SEEK_CUR);
+ lseek(d, 0x150, SEEK_SET);
+ write(d, &script_position, 4);
+ lseek(d, 0, SEEK_END);
+
+ write(d, datas, data_length);
+
+ free(datas);
+}
+
+int main(int argc, char ** argv)
+{
+ int f_script_comp, f_new_script;
+ int i;
+ int num = 0;
+ char nom_du_fichier[100];
+
+ for (i = 384; i < 1844; i = i + 2) {
+ fprintf(stderr, "CD1 - File %d -> Script %d\n", i, num);
+ sprintf(nom_du_fichier, "xeno_d1/ROOMS/%04d.out", i);
+ f_script_comp = open(nom_du_fichier, O_RDONLY);
+ sprintf(nom_du_fichier, "xeno_d1/ROOMS/%04d.out-new", i);
+ f_new_script = open(nom_du_fichier, O_WRONLY | O_CREAT | O_TRUNC, 00644);
+
+ process_one_file(f_script_comp, f_new_script, num);
+
+ close(f_script_comp);
+ num++;
+ }
+ num = 0;
+
+
+ for (i = 379; i < 1838; i = i + 2) {
+ fprintf(stderr, "CD2 - File %d -> Script %d\n", i, num);
+ sprintf(nom_du_fichier, "xeno_d2/ROOMS/%04d.out", i);
+ f_script_comp = open(nom_du_fichier, O_RDONLY);
+ sprintf(nom_du_fichier, "xeno_d2/ROOMS/%04d.out-new", i);
+ f_new_script = open(nom_du_fichier, O_WRONLY | O_CREAT | O_TRUNC, 00644);
+
+ process_one_file(f_script_comp, f_new_script, num);
+
+ close(f_script_comp);
+ num++;
+ }
+ fprintf(stderr, "Done !\n");
+}
diff --git a/Xenogears/script-dec.cpp b/Xenogears/script-dec.cpp
new file mode 100644
index 0000000..9d4faf3
--- /dev/null
+++ b/Xenogears/script-dec.cpp
@@ -0,0 +1,69 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "lz77.h"
+#include "fileutils.h"
+
+void process_one_file(int f, int d, int n) {
+ char nom_du_fichier[100];
+ long script_position, true_length;
+ int i;
+ int f_out;
+
+ if (filesize(f) == 24) return;
+
+ sprintf(nom_du_fichier, "xeno_d%d/ROOMS/%04i", d, n);
+ MKDIR(nom_du_fichier);
+
+ i = 7;
+// for (i = 0; i < 9; i++) {
+// fprintf(stderr, " Processing part %i\n", i);
+ sprintf(nom_du_fichier, "xeno_d%d/ROOMS/%04i/script.comp", d, n);
+// sprintf(nom_du_fichier, "xeno_d%d/ROOMS/%04i/part-%i", d, n, i);
+ f_out = open(nom_du_fichier, O_WRONLY | O_TRUNC | O_CREAT, 00644);
+ lseek(f, 0x130 + i * 4, SEEK_SET);
+ read(f, &script_position, 4);
+ lseek(f, 0x10c + i * 4, SEEK_SET);
+ read(f, &true_length, 4);
+ lseek(f, script_position, SEEK_SET);
+ lz77_decomp(f, f_out, true_length);
+// if (i == 7) {
+// fseek(f_out, 0, SEEK_SET);
+// fread(&true_length, 4, 1, f_out);
+// fprintf(stderr, " (seems to be the script number %i)\n", true_length);
+// }
+ close(f_out);
+// }
+}
+
+int main(void)
+{
+ int f_script_comp;
+ int i;
+ int num = 0;
+ char nom_du_fichier[100];
+
+ for (i = 384; i < 1844; i = i + 2) {
+ fprintf(stderr, "CD 1 - File %d -> Script %d\n", i, num);
+ sprintf(nom_du_fichier, "xeno_d1/ROOMS/%04d.out", i);
+ f_script_comp = open(nom_du_fichier, O_RDONLY);
+
+ process_one_file(f_script_comp, 1, num);
+
+ close(f_script_comp);
+ num++;
+ }
+
+ num = 0;
+
+ for (i = 379; i < 1838; i = i + 2) {
+ fprintf(stderr, "CD 2 - File %d -> Script %d\n", i, num);
+ sprintf(nom_du_fichier, "xeno_d2/ROOMS/%04d.out", i);
+ f_script_comp = open(nom_du_fichier, O_RDONLY);
+
+ process_one_file(f_script_comp, 2, num);
+
+ close(f_script_comp);
+ num++;
+ }
+ fprintf(stderr, "Done !\n");
+}
diff --git a/Xenogears/test-dlz77.cpp b/Xenogears/test-dlz77.cpp
new file mode 100644
index 0000000..98373a6
--- /dev/null
+++ b/Xenogears/test-dlz77.cpp
@@ -0,0 +1,7 @@
+#include <stdio.h>
+#include "lz77.h"
+
+int main(void) {
+ lz77_decomp(0, 1);
+ return 0;
+}
diff --git a/Xenogears/test-lz77.cpp b/Xenogears/test-lz77.cpp
new file mode 100644
index 0000000..8efce98
--- /dev/null
+++ b/Xenogears/test-lz77.cpp
@@ -0,0 +1,7 @@
+#include <stdio.h>
+#include "lz77.h"
+
+int main(void) {
+ lz77_comp(0, 1);
+ return 0;
+}
diff --git a/cd-tool b/cd-tool
new file mode 100755
index 0000000..1c8d03e
--- /dev/null
+++ b/cd-tool
Binary files differ
diff --git a/cd-tool.cpp b/cd-tool.cpp
new file mode 100644
index 0000000..1994561
--- /dev/null
+++ b/cd-tool.cpp
@@ -0,0 +1,273 @@
+/*
+ * PSX-Tools Bundle Pack
+ * Copyright (C) 2002 Nicolas "Pixel" Noble
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <getopt.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include "cdutils.h"
+#include "generic.h"
+#include "fileutils.h"
+
+int lga = 0;
+struct option long_options[] = {
+ {"help", 0, NULL, 'h'},
+ {"ppf", 1, NULL, 'p'},
+ {"mode", 1, NULL, 'm'},
+ {"force", 1, NULL, 'f'},
+ {0, 0, NULL, 0 }
+};
+
+void showhelp(void) {
+ printm(M_BARE,
+"Usage:\n"
+"cd-tool [-m <mode>] [-p <ppf file>] [-f] <isofile> <command> [command args]\n"
+"Where mode can be 1 for MODE 1, 2 for MODE 2, 3 for MODE 2 FORM 1,\n"
+"4 for MODE 2 FORM 2 and 5 for autodetect, which is the default behaviour.\n"
+"\n"
+"Command can be one of:\n"
+" infos - dumps a bunch of infos about the iso.\n"
+" path - dumps the path table.\n"
+" printdir <path> - show the directoy listing of <path>\n"
+" extract-file <file> <path> - extract the file <path> to <file>\n"
+" extract <file> <addr> <size> - extract some sectors to <file>\n"
+" insert-file <file> <path> - insert the file to <path>\n"
+" insert <file> <addr> - insert some sectors at <addr>\n"
+"\n");
+}
+
+int main(int argc, char ** argv) {
+ int type = GUESS, c, size, force = 0, sector;
+ FILE * iso_r, * iso_w;
+ char * ppf = 0, * iso_name = 0, * arg1 = 0, * arg2 = 0, * f;
+
+ verbosity = M_WARNING;
+
+ while ((c = getopt_long(argc, argv, "Hhm:p:f", long_options, NULL)) != EOF) {
+ switch (c) {
+ case 'h':
+ case 'H':
+ case '?':
+ showhelp();
+ exit(0);
+ case 'm':
+ type = atoi(optarg);
+ break;
+ case 'p':
+ ppf = strdup(optarg);
+ break;
+ case 'f':
+ force = 1;
+ break;
+ }
+ }
+
+ if (argc == optind) {
+ showhelp();
+ printm(M_ERROR, "Need an iso filename to work on.\n");
+ exit(-1);
+ }
+
+ iso_name = argv[optind++];
+
+ if (!(iso_r = fopen(iso_name, "r"))) {
+ printm(M_ERROR, "Failed to open %s for reading.\n", iso_name);
+ exit(-1);
+ }
+
+ if (argc == optind) {
+ showhelp();
+ printm(M_ERROR, "Need a command to execute.\n");
+ exit(-1);
+ }
+
+ get_iso_infos(iso_r);
+
+ if (!strcmp(argv[optind], "infos")) {
+ show_iso_infos(iso_r);
+ } else if (!strcmp(argv[optind], "path")) {
+ show_pt_infos(iso_r);
+ } else if (!strcmp(argv[optind], "printdir")) {
+ struct DirEntry dir;
+ optind++;
+ if ((argc - 1) != optind) {
+ showhelp();
+ printm(M_ERROR, "printdir needs one argument.\n");
+ exit(-1);
+ }
+ arg1 = argv[optind];
+ dir = find_path(iso_r, f = strdup(arg1));
+ free(f);
+ if (!dir.R) {
+ printm(M_ERROR, "Path %s was not found on iso.\n", arg1);
+ exit(-1);
+ }
+ if (!(dir.Flags & 2)) {
+ printm(M_ERROR, "Path %s design a file and not a directory.\n", arg1);
+ exit(-1);
+ }
+ show_head_entry();
+ show_dir(iso_r, &dir);
+ } else if (!strcmp(argv[optind], "extract-file")) {
+ struct DirEntry dir;
+ FILE * file;
+
+ optind++;
+ if ((argc - 2) != optind) {
+ showhelp();
+ printm(M_ERROR, "extract-file needs two arguments.\n");
+ exit(-1);
+ }
+ arg1 = argv[optind++];
+ arg2 = argv[optind++];
+ if (!(file = fopen(arg1, "w"))) {
+ printm(M_ERROR, "Failed to open file %s for writing.\n", arg1);
+ exit(-1);
+ }
+ dir = find_path(iso_r, f = strdup(arg2));
+ free(f);
+ if (!dir.R) {
+ printm(M_ERROR, "Path %s was not found on iso.\n", arg2);
+ exit(-1);
+ }
+ printm(M_STATUS, "Reading path %s to file %s.\n", arg2, arg1);
+ read_file(iso_r, file, type, dir.Sector, dir.Size);
+ } else if (!strcmp(argv[optind], "extract")) {
+ FILE * file;
+
+ optind++;
+ if ((argc - 3) != optind) {
+ showhelp();
+ printm(M_ERROR, "extract needs three arguments.\n");
+ exit(-1);
+ }
+ arg1 = argv[optind++];
+ size = atoi(argv[optind++]);
+ sector = atoi(argv[optind++]);
+ if (!(file = fopen(arg1, "w"))) {
+ printm(M_ERROR, "Failed to open file %s for writing.\n", arg1);
+ exit(-1);
+ }
+ printm(M_STATUS, "Reading %i bytes from sector %i to file %s.\n", size, sector, arg1);
+ read_file(iso_r, file, type, sector, size);
+ } else if (!strcmp(argv[optind], "insert-file")) {
+ struct DirEntry dir, * d;
+ unsigned char * buffer;
+ FILE * file;
+ int old_type;
+ if (!(iso_w = fopen(iso_name, "wa"))) {
+ printm(M_ERROR, "Failed to open %s for writing.\n", iso_name);
+ exit(-1);
+ }
+ fseek(iso_w, 0, SEEK_SET);
+
+ if (ppf) {
+ if (open_ppf(ppf, iso_r, "Created by CD-Tool") < 0) {
+ printm(M_ERROR, "Failed to open file %s for writing.\n", ppf);
+ }
+ }
+
+ optind++;
+ if ((argc - 2) != optind) {
+ showhelp();
+ printm(M_ERROR, "insert-file needs two arguments.\n");
+ exit(-1);
+ }
+ arg1 = argv[optind++];
+ arg2 = argv[optind++];
+ if (!(file = fopen(arg1, "r"))) {
+ printm(M_ERROR, "Failed to open file %s for reading.\n", arg1);
+ exit(-1);
+ }
+ dir = find_path(iso_r, f = strdup(arg2));
+ free(f);
+ if (!dir.R) {
+ printm(M_ERROR, "Path %s was not found on iso.\n", arg2);
+ exit(-1);
+ }
+
+ old_type = guess_type(iso_r, dir.Sector);
+
+ if (type == GUESS) {
+ type = old_type;
+ }
+ if (((dir.Size / sec_sizes[old_type]) + ((dir.Size % sec_sizes[old_type]) ? 1 : 0)) <
+ ((filesize(file) / sec_sizes[type]) + ((filesize(file) % sec_sizes[type]) ? 1 : 0))) {
+ if (force) {
+ printm(M_WARNING, "New file too big: %i vs %i in %s.\n", dir.Size, filesize(file), sec_modes[type]);
+ } else {
+ printm(M_ERROR, "New file too big: %i vs %i in %s.\n", dir.Size, filesize(file), sec_modes[type]);
+ exit(-1);
+ }
+ }
+ printm(M_STATUS, "Writing file %s at path %s.\n", arg1, arg2);
+ write_file(iso_r, iso_w, file, type, dir.Sector);
+ printm(M_STATUS, "Updating directory entry.\n");
+ dir = find_parent(iso_r, f = strdup(arg2));
+ free(f);
+ if ((f = strrchr(arg2, '/'))) {
+ f++;
+ } else {
+ f = arg2;
+ }
+ d = find_dir_entry(iso_r, &buffer, &dir, f);
+ d->Size = filesize(file);
+ write_datas(iso_r, iso_w, buffer, GUESS, dir.Sector, dir.Size);
+ free(buffer);
+ } else if (!strcmp(argv[optind], "insert")) {
+ FILE * file;
+ if (!(iso_w = fopen(iso_name, "wa"))) {
+ printm(M_ERROR, "Failed to open %s for writing.\n", iso_name);
+ exit(-1);
+ }
+ fseek(iso_w, 0, SEEK_SET);
+
+ if (ppf) {
+ if (open_ppf(ppf, iso_r, "Created by CD-Tool") < 0) {
+ printm(M_ERROR, "Failed to open file %s for writing.\n", ppf);
+ }
+ }
+
+ optind++;
+ if ((argc - 2) != optind) {
+ showhelp();
+ printm(M_ERROR, "insert needs two arguments.\n");
+ exit(-1);
+ }
+ arg1 = argv[optind++];
+ sector = atoi(argv[optind++]);
+ if (!(file = fopen(arg1, "r"))) {
+ printm(M_ERROR, "Failed to open file %s for reading.\n", arg1);
+ exit(-1);
+ }
+ printm(M_STATUS, "Writing file %s at sector %i.\n", arg1, sector);
+ write_file(iso_r, iso_w, file, type, sector);
+ } else {
+ showhelp();
+ printm(M_ERROR, "Command %s unknow.\n", argv[optind]);
+ exit(-1);
+ }
+
+ exit(0);
+}
+
diff --git a/cdutils.cpp b/cdutils.cpp
new file mode 100644
index 0000000..d697b52
--- /dev/null
+++ b/cdutils.cpp
@@ -0,0 +1,634 @@
+/*
+ * PSX-Tools Bundle Pack
+ * Copyright (C) 2002 Nicolas "Pixel" Noble
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <malloc.h>
+#include "cdutils.h"
+#include "fileutils.h"
+#include "generic.h"
+
+FILE * ppf_file = 0;
+int pt1 = -1, pt2 = -1, snum = 0, ptl = 0, root = 0;
+
+long sec_sizes[5] = {0, 2048, 2336, 2048, 2324};
+long sec_offsts[5] = {0, 16, 16, 24, 24};
+char * sec_modes[5] = {"MODE 0 (no mode)", "MODE 1", "MODE 2", "MODE 2 FORM 1", "MODE 2 FORM 2"};
+
+struct DirEntry rootDir;
+
+unsigned char from_BCD(unsigned char x) {
+ return ((x & 0xff) + ((x & 0xff00) >> 4) * 10);
+}
+
+unsigned char to_BCD(unsigned char x) {
+ return ((x / 10) << 4) | (x % 10);
+}
+
+int is_valid_BCD(unsigned char x) {
+ return (((x & 15) < 10) && ((x >> 4) < 10));
+}
+
+unsigned long from_MSF(unsigned long msf, unsigned long start) {
+ unsigned char
+ f = from_BCD(msf & 0xff),
+ s = from_BCD((msf >> 8) & 0xff),
+ m = from_BCD((msf >> 16) & 0xff);
+
+ return (m * 60 + s) * 75 + f - start;
+}
+
+FILE * open_ppf(char * ppf, FILE * iso, char * comment) {
+ int i, l;
+ char buffer[1024];
+
+ if (!(ppf_file = fopen(ppf, "w")))
+ return ppf_file;
+ fwrite("PPF20\001", 1, 6, ppf_file);
+
+ l = strlen(comment);
+ if (l >= 50) {
+ fwrite(comment, 1, 50, ppf_file);
+ } else {
+ char * t = " ";
+ fwrite(comment, 1, l, ppf_file);
+ for (i = l; i < 50; i++) {
+ fwrite(t, 1, 1, ppf_file);
+ }
+ }
+
+ l = filesize(iso);
+ fwrite(&l, 1, 4, ppf_file);
+
+ fseek(iso, 0x9320, SEEK_SET);
+ fread(buffer, 1, 1024, iso);
+ fwrite(buffer, 1, 1024, ppf_file);
+ return ppf_file;
+}
+
+void write_ppf(unsigned char * old_sec, unsigned char * new_sec, int sec_num) {
+ int i, l = 0, o;
+
+ for (i = 0; i < 2352; i++) {
+ if (old_sec[i] == new_sec[i]) {
+ if (l != 0) {
+ o = 2352 * sec_num + i;
+ fwrite(&o, 1, 4, ppf_file);
+ fwrite(&l, 1, 1, ppf_file);
+ fwrite(new_sec + i - l - 1, 1, l, ppf_file);
+ l = 0;
+ }
+ } else {
+ l++;
+ if (l == 255) {
+ o = 2352 * sec_num + i;
+ fwrite(&o, 1, 4, ppf_file);
+ fwrite(&l, 1, 1, ppf_file);
+ fwrite(new_sec + i - 255, 1, 255, ppf_file);
+ l = 0;
+ }
+ }
+ }
+}
+
+char * format_date(unsigned char * input) {
+ static char output[26];
+
+ memcpy(output, input + 6, 2);
+ output[2] = '/';
+ memcpy(output + 3, input + 4, 2);
+ output[5] = '/';
+ memcpy(output + 6, input, 4);
+ output[10] = ' ';
+ memcpy(output + 11, input + 8, 2);
+ output[13] = ':';
+ memcpy(output + 14, input + 10, 2);
+ output[16] = ':';
+ memcpy(output + 17, input + 12, 2);
+ output[19] = '.';
+ memcpy(output + 20, input + 14, 2);
+ sprintf(output + 22, "%+3.1f", ((float) (*(((char *)input) + 16))) / 4);
+
+ return output;
+}
+
+unsigned short int swap_word(unsigned short int i) {
+ return (i >> 8) | (i << 8);
+}
+
+unsigned long int swap_dword(unsigned long int i) {
+ return (i >> 24) | ((i >> 8) & 0x0000ff00) | ((i << 8) & 0x00ff0000) | (i << 24);
+}
+
+void sector_seek(FILE * f_iso, long sector) {
+ long curpos;
+
+ curpos = (2352 * (long) sector);
+ fseek(f_iso, curpos, SEEK_SET);
+}
+
+int guess_type(FILE * f_iso, int number) {
+ unsigned char header[24];
+
+ if (number >= 0) {
+ sector_seek(f_iso, number);
+ }
+
+ fread(header, 1, 24, f_iso);
+ fseek(f_iso, -24, SEEK_CUR);
+ if (header[15] == 1) {
+ return MODE_1;
+ } else if (header[15] == 2) {
+ if (*((unsigned long *) &(header[16])) == *((unsigned long *) &(header[20]))) {
+ if ((header[16] == 0) && (header[17] == 0) && (header[19] == 0)) {
+ if (header[18] & 0x20) {
+ return MODE_2_FORM_2;
+ } else {
+ return MODE_2_FORM_1;
+ }
+ }
+ }
+ return MODE_2;
+ }
+
+ return MODE_0;
+}
+
+long read_sector(FILE * f_iso, unsigned char * buffer, char type, int number) {
+ if (number >= 0) {
+ sector_seek(f_iso, number);
+ }
+
+ if (type == GUESS) {
+ type = guess_type(f_iso, number);
+ }
+
+ fseek(f_iso, sec_offsts[type], SEEK_CUR);
+ fread(buffer, 1, sec_sizes[type], f_iso);
+ fseek(f_iso, 2352 - sec_offsts[type] - sec_sizes[type], SEEK_CUR);
+ return sec_sizes[type];
+}
+
+void read_datas(FILE * f_iso, unsigned char * buffer, int type, int number, long size) {
+ unsigned char sector[2352];
+ int i, n, reste;
+
+ if (type == GUESS) {
+ type = guess_type(f_iso, number);
+ }
+
+ n = size / sec_sizes[type];
+ reste = size - n * sec_sizes[type];
+
+ sector_seek(f_iso, number);
+ for (i = 0; i < n; i++) {
+ read_sector(f_iso, buffer + i * sec_sizes[type], type);
+ }
+
+ if (reste) {
+ read_sector(f_iso, sector, type);
+ bcopy((char *) sector, (char *) (buffer + n * sec_sizes[type]), reste);
+ }
+}
+
+void read_file(FILE * f_iso, FILE * file, char type, int number, long size) {
+ unsigned char sector[2352];
+ int i, n, reste;
+
+ if (type == GUESS) {
+ type = guess_type(f_iso, number);
+ }
+
+ n = size / sec_sizes[type];
+ reste = size - n * sec_sizes[type];
+
+ sector_seek(f_iso, number);
+ for (i = 0; i < n; i++) {
+ read_sector(f_iso, sector, type);
+ fwrite(sector, 1, sec_sizes[type], file);
+ }
+
+ if (reste) {
+ read_sector(f_iso, sector, type);
+ fwrite(sector, 1, reste, file);
+ }
+}
+
+void write_sector(FILE * f_iso_r, FILE * f_iso_w, unsigned char * buffer, char type, int number) {
+ unsigned char old_sector[2352], new_sector[2352];
+
+ if (type == GUESS) {
+ type = guess_type(f_iso_r, number);
+ }
+
+ if (number >= 0) {
+ sector_seek(f_iso_r, number);
+ sector_seek(f_iso_w, number);
+ }
+
+ fread(old_sector, 1, 2352, f_iso_r);
+
+ minute = old_sector[12];
+ second = old_sector[13];
+ frame = old_sector[14];
+
+ bcopy((char *) old_sector, (char *) new_sector, 2532);
+ bcopy((char *) buffer, (char *) new_sector + sec_offsts[type], sec_sizes[type]);
+
+ do_encode_L2(new_sector, type, 0);
+ if (ppf_file < 0) {
+ fwrite(new_sector, 1, 2352, f_iso_w);
+ } else {
+ write_ppf(old_sector, new_sector, number);
+ }
+}
+
+void write_datas(FILE * f_iso_r, FILE * f_iso_w, unsigned char * buffer, char type, int number, long size) {
+ long nbsectors, i;
+ unsigned char sector[2352];
+
+ if (type == GUESS) {
+ type = guess_type(f_iso_r, number);
+ }
+
+ if (number >= 0) {
+ sector_seek(f_iso_r, number);
+ sector_seek(f_iso_w, number);
+ }
+
+ nbsectors = size / sec_sizes[type];
+
+ for (i = 0; i < nbsectors; i++) {
+ write_sector(f_iso_r, f_iso_w, buffer + i * sec_sizes[type], type, number + i);
+ }
+
+ if (size % sec_sizes[type]) {
+ memset(sector, 0, 2352);
+ bcopy((char *) (buffer + i * sec_sizes[type]), (char *) sector, size % sec_sizes[type]);
+ write_sector(f_iso_r, f_iso_w, sector, type, number + i);
+ }
+}
+
+void write_file(FILE * f_iso_r, FILE * f_iso_w, FILE * file, char type, int number) {
+ long size, nbsectors, i;
+ unsigned char buffer[2352];
+
+ if (type == GUESS) {
+ type = guess_type(f_iso_r, number);
+ }
+
+ if (number >= 0) {
+ sector_seek(f_iso_r, number);
+ sector_seek(f_iso_w, number);
+ }
+
+ size = filesize(file);
+ nbsectors = size / sec_sizes[type];
+
+ if (size % sec_sizes[type]) {
+ nbsectors++;
+ }
+
+ for (i = 0; i < nbsectors; i++) {
+ memset(buffer, 0, 2352);
+ fread(buffer, 1, sec_sizes[type], file);
+ write_sector(f_iso_r, f_iso_w, buffer, type);
+ }
+}
+
+void show_head_entry(void) {
+ printm(M_BARE, "Sector - Size - Date - Time - Flags - Name\n");
+}
+
+int show_entry(struct DirEntry * dir) {
+ char pbuf[200];
+ if (!dir->R) {
+ return 1;
+ }
+
+ strncpy(pbuf, (char *) &(dir->id), dir->N);
+ pbuf[dir->N] = 0;
+
+ printm(M_BARE, "%6i - %8i - %2i/%02i/%02i - %2i:%02i:%02i%+03.1f - %c%c%c%c%c%c%c%c - %s\n",
+ dir->Sector, dir->Size, dir->Day, dir->Month, dir->Year, dir->Hour, dir->Minute, dir->Second, ((float) dir->Offset) / 4,
+ dir->Flags & 1 ? 'H' : '-', dir->Flags & 2 ? 'D' : '-', dir->Flags & 4 ? 'A' : '-', dir->Flags & 8 ? 'R' : '-',
+ dir->Flags & 16 ? 'P' : '-', dir->Flags & 32 ? '1' : '-', dir->Flags & 64 ? '1' : '-', dir->Flags & 128 ? 'C' : '-', pbuf);
+ return dir->R;
+}
+
+int show_dir(FILE * f_iso, struct DirEntry * dir) {
+ unsigned int ptr;
+ unsigned char * buffer;
+
+ if (!(dir->Flags & 2)) {
+ return 0;
+ }
+
+ buffer = (unsigned char *) malloc(dir->Size);
+ read_datas(f_iso, buffer, GUESS, dir->Sector, dir->Size);
+
+ ptr = 0;
+ while(ptr < dir->Size) {
+ ptr += show_entry((struct DirEntry *) &(buffer[ptr]));
+ }
+
+ free(buffer);
+ return 1;
+}
+
+struct DirEntry find_dir_entry(FILE * f_iso, struct DirEntry * dir, char * name) {
+ unsigned int ptr, size;
+ unsigned char * buffer;
+ struct DirEntry r = {0, 0, 0, 0, 0};
+
+ if (!(dir->Flags & 2)) {
+ return r;
+ }
+
+ buffer = (unsigned char *) malloc(size = dir->Size);
+ read_datas(f_iso, buffer, GUESS, dir->Sector, dir->Size);
+
+ ptr = 0;
+ while(ptr < size) {
+ dir = (struct DirEntry *) &(buffer[ptr]);
+ if (!dir->R) {
+ ptr++;
+ } else {
+ if (!strncmp(name, (char *) &(dir->id), dir->N)) {
+ r = *dir;
+ }
+ ptr += dir->R;
+ }
+ }
+
+ free(buffer);
+ return r;
+}
+
+struct DirEntry * find_dir_entry(FILE * f_iso, unsigned char ** bufout, struct DirEntry * dir, char * name) {
+ unsigned int ptr, size;
+ unsigned char * buffer;
+ struct DirEntry * rdir = 0;
+ *bufout = 0;
+
+ if (!(dir->Flags & 2)) {
+ return 0;
+ }
+
+ buffer = (unsigned char *) malloc(size = dir->Size);
+ read_datas(f_iso, buffer, GUESS, dir->Sector, dir->Size);
+
+ ptr = 0;
+ while(ptr < size) {
+ dir = (struct DirEntry *) &(buffer[ptr]);
+ if (!dir->R) {
+ ptr++;
+ } else {
+ if (!strncmp(name, (char *) &(dir->id), dir->N)) {
+ rdir = dir;
+ }
+ ptr += dir->R;
+ }
+ }
+
+ if (rdir->R) {
+ *bufout = buffer;
+ } else {
+ free(buffer);
+ }
+ return rdir;
+}
+
+int show_iso_infos(FILE * f_iso) {
+ unsigned char buffer[2048];
+ char pbuff[130];
+ short int s, nogood = 0;
+
+ read_sector(f_iso, buffer, GUESS, 16);
+
+ printm(M_BARE, "Sector guessed mode : %s\n", sec_modes[guess_type(f_iso, 16)]);
+ printm(M_BARE, "offset-size-info : contents\n");
+ printm(M_BARE, " 0 - 1- 1 : %i\n", buffer[0]);
+ memcpy(pbuff, buffer + 1, 5);
+ pbuff[5] = 0;
+ printm(M_BARE, " 1 - 5-`CD001' : %s\n", pbuff);
+ printm(M_BARE, " 6 - 2- 1 : %i\n", s = *((short int *) &(buffer[6])));
+ printm(M_BARE, "(*this was the signature*)\n");
+ if (buffer[0] != 1) nogood = 1;
+ if (strcmp(pbuff, "CD001")) nogood = 1;
+ if (s != 1) nogood = 1;
+
+ if (nogood) {
+ printm(M_BARE, "Not a valid iso9660 file.\n");
+ return 0;
+ }
+
+ memcpy(pbuff, buffer + 8, 32);
+ pbuff[32] = 0;
+ printm(M_BARE, " 8 - 32- SYSID : %s\n", pbuff);
+ memcpy(pbuff, buffer + 40, 32);
+ pbuff[32] = 0;
+ printm(M_BARE, " 40 - 32- VOLID : %s\n", pbuff);
+ printm(M_BARE, " 80 - 8- SNum : %li\n", *((long int *) &(buffer[80])));
+ printm(M_BARE, " 120 - 4- VOLSiz : %i\n", *((short int *) &(buffer[120])));
+ printm(M_BARE, " 124 - 4- VOLNum : %i\n", *((short int *) &(buffer[124])));
+ printm(M_BARE, " 128 - 4- SSize : %i\n", *((short int *) &(buffer[128])));
+ printm(M_BARE, " 132 - 8- PSize : %li\n", *((long int *) &(buffer[132])));
+ printm(M_BARE, " 140 - 4- 1SLPath: %i\n", *((short int *) &(buffer[140])));
+ printm(M_BARE, " 144 - 4- 2SLPath: %i\n", *((short int *) &(buffer[144])));
+ printm(M_BARE, " 148 - 4- 1SBPath: %i\n", swap_dword(*((short int *) &(buffer[148]))));
+ printm(M_BARE, " 152 - 4- 2SBPath: %i\n", swap_dword(*((short int *) &(buffer[152]))));
+ memcpy(pbuff, buffer + 190, 128);
+ pbuff[128] = 0;
+ printm(M_BARE, " 190 - 128- VStId : %s\n", pbuff);
+ memcpy(pbuff, buffer + 318, 128);
+ pbuff[128] = 0;
+ printm(M_BARE, " 318 - 128- PubId : %s\n", pbuff);
+ memcpy(pbuff, buffer + 446, 128);
+ pbuff[128] = 0;
+ printm(M_BARE, " 446 - 128- DPrId : %s\n", pbuff);
+ memcpy(pbuff, buffer + 574, 128);
+ pbuff[128] = 0;
+ printm(M_BARE, " 574 - 128- AppId : %s\n", pbuff);
+ memcpy(pbuff, buffer + 702, 37);
+ pbuff[37] = 0;
+ printm(M_BARE, " 702 - 37- CpyFile: %s\n", pbuff);
+ memcpy(pbuff, buffer + 739, 37);
+ pbuff[37] = 0;
+ printm(M_BARE, " 739 - 37- AbsFile: %s\n", pbuff);
+ memcpy(pbuff, buffer + 776, 37);
+ pbuff[37] = 0;
+ printm(M_BARE, " 776 - 37- BibFile: %s\n", pbuff);
+ printm(M_BARE, " 813 - 17- DTCreat: %s\n", format_date(&buffer[813]));
+ printm(M_BARE, " 830 - 17- DTModif: %s\n", format_date(&buffer[830]));
+ printm(M_BARE, " 847 - 17- DTExpir: %s\n", format_date(&buffer[847]));
+ printm(M_BARE, " 864 - 17- DTEffec: %s\n", format_date(&buffer[864]));
+
+ printm(M_BARE, "Root record:\n");
+ show_head_entry();
+ show_entry((DirEntry *) &(buffer[156]));
+
+ return 1;
+}
+
+int get_iso_infos(FILE * f_iso) {
+ unsigned char buffer[2048];
+ char pbuff[130];
+ short int s, nogood = 0;
+
+ read_sector(f_iso, buffer, GUESS, 16);
+
+ memcpy(pbuff, buffer + 1, 5);
+ pbuff[5] = 0;
+
+ s = *((short int *) &(buffer[6]));
+ if (buffer[0] != 1) nogood = 1;
+ if (strcmp(pbuff, "CD001")) nogood = 1;
+ if (s != 1) nogood = 1;
+
+ if (nogood) {
+ printm(M_ERROR, "Not a valid iso9660 file.\n");
+ return 0;
+ }
+
+ pt1 = *((short int *) &(buffer[140]));
+ pt2 = *((short int *) &(buffer[144]));
+ snum = *((int *) &(buffer[80]));
+ ptl = *((long int *) &(buffer[132]));
+ rootDir = *((struct DirEntry *) &(buffer[156]));
+ return 1;
+}
+
+int get_pt_infos(FILE * f_iso) {
+ unsigned char * buffer;
+
+ if ((pt1 <= 0) && (pt2 <= 0))
+ if (!get_iso_infos(f_iso))
+ return 0;
+
+ if ((!pt1) & (!pt2)) {
+ printm(M_ERROR, "No path table defined.\n");
+ return 0;
+ }
+
+ buffer = (unsigned char *) malloc(ptl);
+ read_datas(f_iso, buffer, GUESS, !pt1 ? pt2 : pt1, ptl);
+
+ if (buffer[0] == 1)
+ if (buffer[1] == 0)
+ if (buffer[6] == 1)
+ if (buffer[7] == 0)
+ if (buffer[8] == 0)
+ if (buffer[9] == 0)
+ root = *((unsigned long int *) &(buffer[2]));
+
+ free(buffer);
+ return root ? 1 : 0;
+}
+
+int show_pt_infos(FILE * f_iso) {
+ unsigned char * buffer;
+ char pbuf[100];
+ int i, ptr;
+
+ if ((pt1 <= 0) && (pt2 <= 0))
+ if (!get_iso_infos(f_iso))
+ return 0;
+
+ if ((!pt1) & (!pt2)) {
+ printm(M_ERROR, "No path table defined.\n");
+ return 0;
+ }
+
+ buffer = (unsigned char *) malloc(ptl);
+ read_datas(f_iso, buffer, GUESS, !pt1 ? pt2 : pt1, ptl);
+
+ printm(M_BARE, "node^paren@sector : name\n");
+ for (ptr = 0, i = 1; buffer[ptr]; ptr += ptr & 1, i++) {
+ strncpy(pbuf, (char *) &(buffer[8 + ptr]), buffer[ptr]);
+ pbuf[buffer[ptr]] = 0;
+ printm(M_BARE, "%3i ^ %3i @ %6i: %s\n", i, *((unsigned short *) &(buffer[6 + ptr])), *((unsigned long *) &(buffer[2 + ptr])), pbuf);
+ ptr += 8 + buffer[ptr];
+ }
+
+ free(buffer);
+ return 1;
+}
+
+struct DirEntry find_path(FILE * f_iso, char * path) {
+ char ** pts = split(path, '/');
+ struct DirEntry dir = {0, 0, 0, 0, 0};
+
+ if ((pt1 <= 0) && (pt2 <= 0))
+ if (!get_iso_infos(f_iso))
+ return dir;
+
+ if ((!pt1) & (!pt2)) {
+ printm(M_ERROR, "No path table defined.\n");
+ return dir;
+ }
+
+ if (!**pts)
+ pts++;
+
+ for (dir = rootDir; *pts; pts++) {
+ if (!strlen(*pts))
+ continue;
+ dir = find_dir_entry(f_iso, &dir, *pts);
+ if (!dir.R)
+ return dir;
+ }
+
+ return dir;
+}
+
+struct DirEntry find_parent(FILE * f_iso, char * path) {
+ char ** pts, * p;
+ struct DirEntry dir = {0, 0, 0, 0, 0};
+
+ if ((p = strchr(path, '/'))) {
+ *p = 0;
+ }
+ if (!*path) {
+ return rootDir;
+ }
+ pts = split(path, '/');
+
+ if ((pt1 <= 0) && (pt2 <= 0))
+ if (!get_iso_infos(f_iso))
+ return dir;
+
+ if ((!pt1) & (!pt2)) {
+ printm(M_ERROR, "No path table defined.\n");
+ return dir;
+ }
+
+ if (!**pts)
+ pts++;
+
+ for (dir = rootDir; *pts; pts++) {
+ if (!strlen(*pts))
+ continue;
+ dir = find_dir_entry(f_iso, &dir, *pts);
+ if (!dir.R)
+ return dir;
+ }
+
+ return dir;
+}
diff --git a/cdutils.h b/cdutils.h
new file mode 100644
index 0000000..b3aace5
--- /dev/null
+++ b/cdutils.h
@@ -0,0 +1,83 @@
+/*
+ * PSX-Tools Bundle Pack
+ * Copyright (C) 2002 Nicolas "Pixel" Noble
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __CDUTILS_H__
+#define __CDUTILS_H__
+
+#include <yazedc.h>
+
+#define GUESS 5
+
+struct DirEntry {
+ unsigned char R;
+ unsigned char NExt;
+ unsigned long Sector;
+ unsigned long BESector;
+ unsigned long Size;
+ unsigned long BESize;
+ unsigned char Year;
+ unsigned char Month;
+ unsigned char Day;
+ unsigned char Hour;
+ unsigned char Minute;
+ unsigned char Second;
+ unsigned char Offset;
+ unsigned char Flags;
+ unsigned char FileUnit;
+ unsigned char FileGap;
+ unsigned short VolSeq;
+ unsigned short BEVolSeq;
+ unsigned char N;
+ char id;
+} __attribute__((packed));
+
+extern struct DirEntry rootDir;
+
+extern long sec_sizes[];
+extern long sec_offsts[];
+extern char * sec_modes[];
+
+FILE * open_ppf(char * ppf, FILE * iso, char * comment);
+unsigned short int swap_word(unsigned short int i);
+unsigned long int swap_dword(unsigned long int i);
+int guess_type(FILE * f_iso, int number);
+void sector_seek(FILE * f_iso, long sector);
+long read_sector(FILE * f_iso, unsigned char * buffer, char type, int number = -1);
+void read_datas(FILE * f_iso, unsigned char * buffer, int type, int number, long size);
+void read_file(FILE * f_iso, FILE * file, char type, int number, long size);
+void write_sector(FILE * f_iso_r, FILE * f_iso_w, unsigned char * buffer, char type, int number = -1);
+void write_datas(FILE * f_iso_r, FILE * f_iso_w, unsigned char * buffer, char type, int number, long size);
+void write_file(FILE * f_iso_r, FILE * f_iso_w, FILE * file, char type, int number = -1);
+int get_iso_infos(FILE * h);
+int show_iso_infos(FILE * h);
+int get_pt_infos(FILE * h);
+int show_pt_infos(FILE * h);
+struct DirEntry find_path(FILE * h, char * path);
+struct DirEntry find_parent(FILE * h, char * path);
+void show_head_entry(void);
+int show_entry(struct DirEntry * dir);
+int show_dir(FILE * h, struct DirEntry * dir);
+struct DirEntry find_dir_entry(FILE * h, struct DirEntry * dir, char * name);
+struct DirEntry * find_dir_entry(FILE * h, unsigned char ** buffer, struct DirEntry * dir, char * name);
+unsigned char from_BCD(unsigned char x);
+unsigned char to_BCD(unsigned char x);
+int is_valid_BCD(unsigned char x);
+unsigned long from_MSF(unsigned long msf, unsigned long start = 150);
+
+#endif
diff --git a/crctable.out b/crctable.out
new file mode 100644
index 0000000..47842cd
--- /dev/null
+++ b/crctable.out
@@ -0,0 +1,91 @@
+/*****************************************************************/
+/* */
+/* CRC LOOKUP TABLE */
+/* ================ */
+/* The following CRC lookup table was generated automagically */
+/* by the Rocksoft^tm Model CRC Algorithm Table Generation */
+/* Program V1.0 using the following model parameters: */
+/* */
+/* Width : 4 bytes. */
+/* Poly : 0x8001801BL */
+/* Reverse : TRUE. */
+/* */
+/* For more information on the Rocksoft^tm Model CRC Algorithm, */
+/* see the document titled "A Painless Guide to CRC Error */
+/* Detection Algorithms" by Ross Williams */
+/* (ross@guest.adelaide.edu.au.). This document is likely to be */
+/* in the FTP archive "ftp.adelaide.edu.au/pub/rocksoft". */
+/* */
+/*****************************************************************/
+
+unsigned long EDC_crctable[256] =
+{
+ 0x00000000L, 0x90910101L, 0x91210201L, 0x01B00300L,
+ 0x92410401L, 0x02D00500L, 0x03600600L, 0x93F10701L,
+ 0x94810801L, 0x04100900L, 0x05A00A00L, 0x95310B01L,
+ 0x06C00C00L, 0x96510D01L, 0x97E10E01L, 0x07700F00L,
+ 0x99011001L, 0x09901100L, 0x08201200L, 0x98B11301L,
+ 0x0B401400L, 0x9BD11501L, 0x9A611601L, 0x0AF01700L,
+ 0x0D801800L, 0x9D111901L, 0x9CA11A01L, 0x0C301B00L,
+ 0x9FC11C01L, 0x0F501D00L, 0x0EE01E00L, 0x9E711F01L,
+ 0x82012001L, 0x12902100L, 0x13202200L, 0x83B12301L,
+ 0x10402400L, 0x80D12501L, 0x81612601L, 0x11F02700L,
+ 0x16802800L, 0x86112901L, 0x87A12A01L, 0x17302B00L,
+ 0x84C12C01L, 0x14502D00L, 0x15E02E00L, 0x85712F01L,
+ 0x1B003000L, 0x8B913101L, 0x8A213201L, 0x1AB03300L,
+ 0x89413401L, 0x19D03500L, 0x18603600L, 0x88F13701L,
+ 0x8F813801L, 0x1F103900L, 0x1EA03A00L, 0x8E313B01L,
+ 0x1DC03C00L, 0x8D513D01L, 0x8CE13E01L, 0x1C703F00L,
+ 0xB4014001L, 0x24904100L, 0x25204200L, 0xB5B14301L,
+ 0x26404400L, 0xB6D14501L, 0xB7614601L, 0x27F04700L,
+ 0x20804800L, 0xB0114901L, 0xB1A14A01L, 0x21304B00L,
+ 0xB2C14C01L, 0x22504D00L, 0x23E04E00L, 0xB3714F01L,
+ 0x2D005000L, 0xBD915101L, 0xBC215201L, 0x2CB05300L,
+ 0xBF415401L, 0x2FD05500L, 0x2E605600L, 0xBEF15701L,
+ 0xB9815801L, 0x29105900L, 0x28A05A00L, 0xB8315B01L,
+ 0x2BC05C00L, 0xBB515D01L, 0xBAE15E01L, 0x2A705F00L,
+ 0x36006000L, 0xA6916101L, 0xA7216201L, 0x37B06300L,
+ 0xA4416401L, 0x34D06500L, 0x35606600L, 0xA5F16701L,
+ 0xA2816801L, 0x32106900L, 0x33A06A00L, 0xA3316B01L,
+ 0x30C06C00L, 0xA0516D01L, 0xA1E16E01L, 0x31706F00L,
+ 0xAF017001L, 0x3F907100L, 0x3E207200L, 0xAEB17301L,
+ 0x3D407400L, 0xADD17501L, 0xAC617601L, 0x3CF07700L,
+ 0x3B807800L, 0xAB117901L, 0xAAA17A01L, 0x3A307B00L,
+ 0xA9C17C01L, 0x39507D00L, 0x38E07E00L, 0xA8717F01L,
+ 0xD8018001L, 0x48908100L, 0x49208200L, 0xD9B18301L,
+ 0x4A408400L, 0xDAD18501L, 0xDB618601L, 0x4BF08700L,
+ 0x4C808800L, 0xDC118901L, 0xDDA18A01L, 0x4D308B00L,
+ 0xDEC18C01L, 0x4E508D00L, 0x4FE08E00L, 0xDF718F01L,
+ 0x41009000L, 0xD1919101L, 0xD0219201L, 0x40B09300L,
+ 0xD3419401L, 0x43D09500L, 0x42609600L, 0xD2F19701L,
+ 0xD5819801L, 0x45109900L, 0x44A09A00L, 0xD4319B01L,
+ 0x47C09C00L, 0xD7519D01L, 0xD6E19E01L, 0x46709F00L,
+ 0x5A00A000L, 0xCA91A101L, 0xCB21A201L, 0x5BB0A300L,
+ 0xC841A401L, 0x58D0A500L, 0x5960A600L, 0xC9F1A701L,
+ 0xCE81A801L, 0x5E10A900L, 0x5FA0AA00L, 0xCF31AB01L,
+ 0x5CC0AC00L, 0xCC51AD01L, 0xCDE1AE01L, 0x5D70AF00L,
+ 0xC301B001L, 0x5390B100L, 0x5220B200L, 0xC2B1B301L,
+ 0x5140B400L, 0xC1D1B501L, 0xC061B601L, 0x50F0B700L,
+ 0x5780B800L, 0xC711B901L, 0xC6A1BA01L, 0x5630BB00L,
+ 0xC5C1BC01L, 0x5550BD00L, 0x54E0BE00L, 0xC471BF01L,
+ 0x6C00C000L, 0xFC91C101L, 0xFD21C201L, 0x6DB0C300L,
+ 0xFE41C401L, 0x6ED0C500L, 0x6F60C600L, 0xFFF1C701L,
+ 0xF881C801L, 0x6810C900L, 0x69A0CA00L, 0xF931CB01L,
+ 0x6AC0CC00L, 0xFA51CD01L, 0xFBE1CE01L, 0x6B70CF00L,
+ 0xF501D001L, 0x6590D100L, 0x6420D200L, 0xF4B1D301L,
+ 0x6740D400L, 0xF7D1D501L, 0xF661D601L, 0x66F0D700L,
+ 0x6180D800L, 0xF111D901L, 0xF0A1DA01L, 0x6030DB00L,
+ 0xF3C1DC01L, 0x6350DD00L, 0x62E0DE00L, 0xF271DF01L,
+ 0xEE01E001L, 0x7E90E100L, 0x7F20E200L, 0xEFB1E301L,
+ 0x7C40E400L, 0xECD1E501L, 0xED61E601L, 0x7DF0E700L,
+ 0x7A80E800L, 0xEA11E901L, 0xEBA1EA01L, 0x7B30EB00L,
+ 0xE8C1EC01L, 0x7850ED00L, 0x79E0EE00L, 0xE971EF01L,
+ 0x7700F000L, 0xE791F101L, 0xE621F201L, 0x76B0F300L,
+ 0xE541F401L, 0x75D0F500L, 0x7460F600L, 0xE4F1F701L,
+ 0xE381F801L, 0x7310F900L, 0x72A0FA00L, 0xE231FB01L,
+ 0x71C0FC00L, 0xE151FD01L, 0xE0E1FE01L, 0x7070FF00L
+};
+
+/*****************************************************************/
+/* End of CRC Lookup Table */
+/*****************************************************************/
diff --git a/crctables b/crctables
new file mode 100644
index 0000000..3dd89c1
--- /dev/null
+++ b/crctables
@@ -0,0 +1,142 @@
+static unsigned char rs_l12_alog[255] = {
+ 1, 2, 4, 8,16,32,64,128,29,58,116,232,205,135,19,38,76,152,45,90,180,117,234,201,143, 3, 6,12,24,48,96,192,157,39,78,156,37,74,148,53,106,212,181,119,238,193,159,35,70,140, 5,10,20,40,80,160,93,186,105,210,185,111,222,161,95,190,97,194,153,47,94,188,101,202,137,15,30,60,120,240,253,231,211,187,107,214,177,127,254,225,223,163,91,182,113,226,217,175,67,134,17,34,68,136,13,26,52,104,208,189,103,206,129,31,62,124,248,237,199,147,59,118,236,197,151,51,102,204,133,23,46,92,184,109,218,169,79,158,33,66,132,21,42,84,168,77,154,41,82,164,85,170,73,146,57,114,228,213,183,115,230,209,191,99,198,145,63,126,252,229,215,179,123,246,241,255,227,219,171,75,150,49,98,196,149,55,110,220,165,87,174,65,130,25,50,100,200,141, 7,14,28,56,112,224,221,167,83,166,81,162,89,178,121,242,249,239,195,155,43,86,172,69,138, 9,18,36,72,144,61,122,244,245,247,243,251,235,203,139,11,22,44,88,176,125,250,233,207,131,27,54,108,216,173,71,142,};
+static unsigned char rs_l12_log[256] = {
+ 0, 0, 1,25, 2,50,26,198, 3,223,51,238,27,104,199,75, 4,100,224,14,52,141,239,129,28,193,105,248,200, 8,76,113, 5,138,101,47,225,36,15,33,53,147,142,218,240,18,130,69,29,181,194,125,106,39,249,185,201,154, 9,120,77,228,114,166, 6,191,139,98,102,221,48,253,226,152,37,179,16,145,34,136,54,208,148,206,143,150,219,189,241,210,19,92,131,56,70,64,30,66,182,163,195,72,126,110,107,58,40,84,250,133,186,61,202,94,155,159,10,21,121,43,78,212,229,172,115,243,167,87, 7,112,192,247,140,128,99,13,103,74,222,237,49,197,254,24,227,165,153,119,38,184,180,124,17,68,146,217,35,32,137,46,55,63,209,91,149,188,207,205,144,135,151,178,220,252,190,97,242,86,211,171,20,42,93,158,132,60,57,83,71,109,65,162,31,45,67,216,183,123,164,118,196,23,73,236,127,12,111,246,108,161,59,82,41,157,85,170,251,96,134,177,187,204,62,90,203,89,95,176,156,169,160,81,11,245,22,235,122,117,44,215,79,174,213,233,230,231,173,232,116,214,244,234,168,80,88,175,};
+static unsigned char rs_sub_rw_alog[63] = {
+ 1, 2, 4, 8,16,32, 3, 6,12,24,48,35, 5,10,20,40,19,38,15,30,60,59,53,41,17,34, 7,14,28,56,51,37, 9,18,36,11,22,44,27,54,47,29,58,55,45,25,50,39,13,26,52,43,21,42,23,46,31,62,63,61,57,49,33,};
+static unsigned char rs_sub_rw_log[63] = {
+ 0, 0, 1, 6, 2,12, 7,26, 3,32,13,35, 8,48,27,18, 4,24,33,16,14,52,36,54, 9,45,49,38,28,41,19,56, 5,62,25,11,34,31,17,47,15,23,53,51,37,44,55,40,10,61,46,30,50,22,39,43,29,60,42,21,20,59,57,};
+static unsigned char SQ[2][2] = {
+{26,6,},
+{7,1,},
+};
+static unsigned char SP[4][20] = {
+{57,38,44,29,17,57,53,58,60,39,12,38,18,41,6,25,39,37,5,18,},
+{38,62,42,13,30,11,46,5,54,26,12,49,48,46,8,50,28,9,12,39,},
+{32,18,41,49,52,62,38,36,39,58,37,24,34,51,51,27,28,36,22,21,},
+{44,50,35,23,0,59,1,3,45,18,44,24,47,12,31,45,43,11,24,6,},
+};
+static unsigned char AQ[4][24] = {
+{58,152,173,95,88,43,134,205,143,131,163,75,37,109,194,159,168,227,153,59,101,},
+{30,214,148,138,112,154,157,96,49,198,189,249,83,23,70,237,70,41,47,52,125,247,},
+{162,244,13,171,213,236,71,177,253,162,59,78,46,68,238,112,147,197,115,200,117,15,236,},
+{158,179,101,94,49,140,211,149,137,169,81,6,33,30,27,24,21,18,15,12,9,6,3,0,},
+};
+static unsigned char AP[4][32] = {
+{140,143,52,103,249,142,180,197,5,155,153,132,143,244,101,76,102,155,203,104,58,152,173,95,88,43,134,205,143,131,163,75,},
+{104,97,17,162,205,252,218,199,202,41,136,106,119,238,193,103,123,242,83,178,30,214,148,138,112,154,157,96,49,198,189,249,},
+{240,119,29,185,67,11,131,40,7,41,80,147,151,17,245,253,208,66,228,116,162,244,13,171,213,236,71,177,253,162,59,78,},
+{149,58,109,0,148,186,203,11,161,159,138,149,250,107,82,108,161,209,110,64,158,179,101,94,49,140,211,149,137,169,81,6,},
+};
+static unsigned char DQ[2][43] = {
+{190,96,250,132,59,81,159,154,200,7,111,245,10,20,41,156,168,79,173,231,229,171,210,240,17,67,215,43,120,8,199,74,102,220,251,95,175,87,166,113,75,198,25,},
+{97,251,133,60,82,160,155,201,8,112,246,11,21,42,157,169,80,174,232,230,172,211,241,18,68,216,44,121,9,200,75,103,221,252,96,176,88,167,114,76,199,26,1,},
+};
+static unsigned char DP[2][24] = {
+{231,229,171,210,240,17,67,215,43,120,8,199,74,102,220,251,95,175,87,166,113,75,198,25,},
+{230,172,211,241,18,68,216,44,121,9,200,75,103,221,252,96,176,88,167,114,76,199,26,1,},
+};
+static unsigned char yellowbook_scrambler[2340] = {
+ 1,128,0,96,0,40,0,30,128,8,96,6,168,2,254,129,128,96,96,40,40,30,158,
+ 136,104,102,174,170,252,127,1,224,0,72,0,54,128,22,224,14,200,4,86,131,126,225,
+ 224,72,72,54,182,150,246,238,198,204,82,213,253,159,1,168,0,126,128,32,96,24,40,
+ 10,158,135,40,98,158,169,168,126,254,160,64,120,48,34,148,25,175,74,252,55,1,214,
+ 128,94,224,56,72,18,182,141,182,229,182,203,54,215,86,222,190,216,112,90,164,59,59,
+ 83,83,125,253,225,129,136,96,102,168,42,254,159,0,104,0,46,128,28,96,9,232,6,
+ 206,130,212,97,159,104,104,46,174,156,124,105,225,238,200,76,86,181,254,247,0,70,128,
+ 50,224,21,136,15,38,132,26,227,75,9,247,70,198,178,210,245,157,135,41,162,158,249,
+ 168,66,254,177,128,116,96,39,104,26,174,139,60,103,81,234,188,79,49,244,20,71,79,
+ 114,180,37,183,91,54,187,86,243,126,197,224,83,8,61,198,145,146,236,109,141,237,165,
+ 141,187,37,179,91,53,251,87,3,126,129,224,96,72,40,54,158,150,232,110,206,172,84,
+ 125,255,97,128,40,96,30,168,8,126,134,160,98,248,41,130,158,225,168,72,126,182,160,
+ 118,248,38,194,154,209,171,28,127,73,224,54,200,22,214,142,222,228,88,75,122,183,99,
+ 54,169,214,254,222,192,88,80,58,188,19,49,205,212,85,159,127,40,32,30,152,8,106,
+ 134,175,34,252,25,129,202,224,87,8,62,134,144,98,236,41,141,222,229,152,75,42,183,
+ 95,54,184,22,242,142,197,164,83,59,125,211,97,157,232,105,142,174,228,124,75,97,247,
+ 104,70,174,178,252,117,129,231,32,74,152,55,42,150,159,46,232,28,78,137,244,102,199,
+ 106,210,175,29,188,9,177,198,244,82,199,125,146,161,173,184,125,178,161,181,184,119,50,
+ 166,149,186,239,51,12,21,197,207,19,20,13,207,69,148,51,47,85,220,63,25,208,10,
+ 220,7,25,194,138,209,167,28,122,137,227,38,201,218,214,219,30,219,72,91,118,187,102,
+ 243,106,197,239,19,12,13,197,197,147,19,45,205,221,149,153,175,42,252,31,1,200,0,
+ 86,128,62,224,16,72,12,54,133,214,227,30,201,200,86,214,190,222,240,88,68,58,179,
+ 83,53,253,215,1,158,128,104,96,46,168,28,126,137,224,102,200,42,214,159,30,232,8,
+ 78,134,180,98,247,105,134,174,226,252,73,129,246,224,70,200,50,214,149,158,239,40,76,
+ 30,181,200,119,22,166,142,250,228,67,11,113,199,100,82,171,125,191,97,176,40,116,30,
+ 167,72,122,182,163,54,249,214,194,222,209,152,92,106,185,239,50,204,21,149,207,47,20,
+ 28,15,73,196,54,211,86,221,254,217,128,90,224,59,8,19,70,141,242,229,133,139,35,
+ 39,89,218,186,219,51,27,85,203,127,23,96,14,168,4,126,131,96,97,232,40,78,158,
+ 180,104,119,110,166,172,122,253,227,1,137,192,102,208,42,220,31,25,200,10,214,135,30,
+ 226,136,73,166,182,250,246,195,6,209,194,220,81,153,252,106,193,239,16,76,12,53,197,
+ 215,19,30,141,200,101,150,171,46,255,92,64,57,240,18,196,13,147,69,173,243,61,133,
+ 209,163,28,121,201,226,214,201,158,214,232,94,206,184,84,114,191,101,176,43,52,31,87,
+ 72,62,182,144,118,236,38,205,218,213,155,31,43,72,31,118,136,38,230,154,202,235,23,
+ 15,78,132,52,99,87,105,254,174,192,124,80,33,252,24,65,202,176,87,52,62,151,80,
+ 110,188,44,113,221,228,89,139,122,231,99,10,169,199,62,210,144,93,172,57,189,210,241,
+ 157,132,105,163,110,249,236,66,205,241,149,132,111,35,108,25,237,202,205,151,21,174,143,
+ 60,100,17,235,76,79,117,244,39,7,90,130,187,33,179,88,117,250,167,3,58,129,211,
+ 32,93,216,57,154,146,235,45,143,93,164,57,187,82,243,125,133,225,163,8,121,198,162,
+ 210,249,157,130,233,161,142,248,100,66,171,113,191,100,112,43,100,31,107,72,47,118,156,
+ 38,233,218,206,219,20,91,79,123,116,35,103,89,234,186,207,51,20,21,207,79,20,52,
+ 15,87,68,62,179,80,117,252,39,1,218,128,91,32,59,88,19,122,141,227,37,137,219,
+ 38,219,90,219,123,27,99,75,105,247,110,198,172,82,253,253,129,129,160,96,120,40,34,
+ 158,153,168,106,254,175,0,124,0,33,192,24,80,10,188,7,49,194,148,81,175,124,124,
+ 33,225,216,72,90,182,187,54,243,86,197,254,211,0,93,192,57,144,18,236,13,141,197,
+ 165,147,59,45,211,93,157,249,169,130,254,225,128,72,96,54,168,22,254,142,192,100,80,
+ 43,124,31,97,200,40,86,158,190,232,112,78,164,52,123,87,99,126,169,224,126,200,32,
+ 86,152,62,234,144,79,44,52,29,215,73,158,182,232,118,206,166,212,122,223,99,24,41,
+ 202,158,215,40,94,158,184,104,114,174,165,188,123,49,227,84,73,255,118,192,38,208,26,
+ 220,11,25,199,74,210,183,29,182,137,182,230,246,202,198,215,18,222,141,152,101,170,171,
+ 63,63,80,16,60,12,17,197,204,83,21,253,207,1,148,0,111,64,44,48,29,212,9,
+ 159,70,232,50,206,149,148,111,47,108,28,45,201,221,150,217,174,218,252,91,1,251,64,
+ 67,112,49,228,20,75,79,119,116,38,167,90,250,187,3,51,65,213,240,95,4,56,3,
+ 82,129,253,160,65,184,48,114,148,37,175,91,60,59,81,211,124,93,225,249,136,66,230,
+ 177,138,244,103,7,106,130,175,33,188,24,113,202,164,87,59,126,147,96,109,232,45,142,
+ 157,164,105,187,110,243,108,69,237,243,13,133,197,163,19,57,205,210,213,157,159,41,168,
+ 30,254,136,64,102,176,42,244,31,7,72,2,182,129,182,224,118,200,38,214,154,222,235,
+ 24,79,74,180,55,55,86,150,190,238,240,76,68,53,243,87,5,254,131,0,97,192,40,
+ 80,30,188,8,113,198,164,82,251,125,131,97,161,232,120,78,162,180,121,183,98,246,169,
+ 134,254,226,192,73,144,54,236,22,205,206,213,148,95,47,120,28,34,137,217,166,218,250,
+ 219,3,27,65,203,112,87,100,62,171,80,127,124,32,33,216,24,90,138,187,39,51,90,
+ 149,251,47,3,92,1,249,192,66,208,49,156,20,105,207,110,212,44,95,93,248,57,130,
+ 146,225,173,136,125,166,161,186,248,115,2,165,193,187,16,115,76,37,245,219,7,27,66,
+ 139,113,167,100,122,171,99,63,105,208,46,220,28,89,201,250,214,195,30,209,200,92,86,
+ 185,254,242,192,69,144,51,44,21,221,207,25,148,10,239,71,12,50,133,213,163,31,57,
+ 200,18,214,141,158,229,168,75,62,183,80,118,188,38,241,218,196,91,19,123,77,227,117,
+ 137,231,38,202,154,215,43,30,159,72,104,54,174,150,252,110,193,236,80,77,252,53,129,
+ 215,32,94,152,56,106,146,175,45,188,29,177,201,180,86,247,126,198,160,82,248,61,130,
+ 145,161,172,120,125,226,161,137,184,102,242,170,197,191,19,48,13,212,5,159,67,40,49,
+ 222,148,88,111,122,172,35,61,217,209,154,220,107,25,239,74,204,55,21,214,143,30,228,
+ 8,75,70,183,114,246,165,134,251,34,195,89,145,250,236,67,13,241,197,132,83,35,125,
+ 217,225,154,200,107,22,175,78,252,52,65,215,112,94,164,56,123,82,163,125,185,225,178,
+ 200,117,150,167,46,250,156,67,41,241,222,196,88,83,122,189,227,49,137,212,102,223,106,
+ 216,47,26,156,11,41,199,94,210,184,93,178,185,181,178,247,53,134,151,34,238,153,140,
+ 106,229,239,11,12,7,69,194,179,17,181,204,119,21,230,143,10,228,7,11,66,135,113,
+ 162,164,121,187,98,243,105,133,238,227,12,73,197,246,211,6,221,194,217,145,154,236,107,
+ 13,239,69,140,51,37,213,219,31,27,72,11,118,135,102,226,170,201,191,22,240,14,196,
+ 4,83,67,125,241,225,132,72,99,118,169,230,254,202,192,87,16,62,140,16,101,204,43,
+ 21,223,79,24,52,10,151,71,46,178,156,117,169,231,62,202,144,87,44,62,157,208,105,
+ 156,46,233,220,78,217,244,90,199,123,18,163,77,185,245,178,199,53,146,151,45,174,157,
+ 188,105,177,238,244,76,71,117,242,167,5,186,131,51,33,213,216,95,26,184,11,50,135,
+ 85,162,191,57,176,18,244,13,135,69,162,179,57,181,210,247,29,134,137,162,230,249,138,
+ 194,231,17,138,140,103,37,234,155,15,43,68,31,115,72,37,246,155,6,235,66,207,113,
+ 148,36,111,91,108,59,109,211,109,157,237,169,141,190,229,176,75,52,55,87,86,190,190,
+ 240,112,68,36,51,91,85,251,127,3,96,1,232,0,78,128,52,96,23,104,14,174,132,
+ 124,99,97,233,232,78,206,180,84,119,127,102,160,42,248,31,2,136,1,166,128,122,224,
+ 35,8,25,198,138,210,231,29,138,137,167,38,250,154,195,43,17,223,76,88,53,250,151,
+ 3,46,129,220,96,89,232,58,206,147,20,109,207,109,148,45,175,93,188,57,177,210,244,
+ 93,135,121,162,162,249,185,130,242,225,133,136,99,38,169,218,254,219,0,91,64,59,112,
+ 19,100,13,235,69,143,115,36,37,219,91,27,123,75,99,119,105,230,174,202,252,87,1,
+ 254,128,64,96,48,40,20,30,143,72,100,54,171,86,255,126,192,32,80,24,60,10,145,
+ 199,44,82,157,253,169,129,190,224,112,72,36,54,155,86,235,126,207,96,84,40,63,94,
+ 144,56,108,18,173,205,189,149,177,175,52,124,23,97,206,168,84,126,191,96,112,40,36,
+ 30,155,72,107,118,175,102,252,42,193,223,16,88,12,58,133,211,35,29,217,201,154,214,
+ 235,30,207,72,84,54,191,86,240,62,196,16,83,76,61,245,209,135,28,98,137,233,166,
+ 206,250,212,67,31,113,200,36,86,155,126,235,96,79,104,52,46,151,92,110,185,236,114,
+ 205,229,149,139,47,39,92,26,185,203,50,215,85,158,191,40,112,30,164,8,123,70,163,
+ 114,249,229,130,203,33,151,88,110,186,172,115,61,229,209,139,28,103,73,234,182,207,54,
+ 212,22,223,78,216,52,90,151,123,46,163,92,121,249,226,194,201,145,150,236,110,205,236,
+ 85,141,255,37,128,27,32,11,88,7,122,130,163,33,185,216,114,218,165,155,59,43,83,
+ 95,125,248,33,130,152,97,170,168,127,62,160,16,120,12,34,133,217,163,26,249,203,2,
+ 215,65,158,176,104,116,46,167,92,122,185,227,50,201,213,150,223,46,216,28,90,137,251,
+ 38,195,90,209,251,28,67,73,241,246,196,70,211,114,221,229,153,
+};
diff --git a/fileutils.cpp b/fileutils.cpp
new file mode 100644
index 0000000..9091f29
--- /dev/null
+++ b/fileutils.cpp
@@ -0,0 +1,50 @@
+/*
+ * PSX-Tools Bundle Pack
+ * Copyright (C) 2002 Nicolas "Pixel" Noble
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "generic.h"
+
+unsigned long filesize(FILE * f_iso)
+{
+ long curpos, length;
+
+ curpos = ftell(f_iso);
+ fseek(f_iso, 0, SEEK_END);
+ length = ftell(f_iso);
+ fseek(f_iso, curpos, SEEK_SET);
+ return length;
+}
+
+void copy(FILE * s, FILE * d, long size) {
+ long i;
+ unsigned char c;
+ long r;
+
+ for (i = 0; i < size; i++) {
+ r = fread(&c, 1, 1, s);
+ if (r == 0) {
+ break;
+ }
+ fwrite(&c, 1, 1, d);
+ }
+}
diff --git a/fileutils.h b/fileutils.h
new file mode 100644
index 0000000..6a37f7e
--- /dev/null
+++ b/fileutils.h
@@ -0,0 +1,40 @@
+/*
+ * PSX-Tools Bundle Pack
+ * Copyright (C) 2002 Nicolas "Pixel" Noble
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __FILEUTILS_H__
+#define __FILEUTILS_H__
+
+#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+unsigned long filesize(FILE * f_iso);
+void copy(FILE * s, FILE * d, long size);
+
+#if defined __linux__ || defined __CYGWIN32__
+#define MKDIR(name) mkdir(name, 0777)
+#elif defined __MINGW32_VERSION
+#define MKDIR mkdir
+#else
+#error Unknow compiler/platform
+#endif
+
+#endif
diff --git a/generic.cpp b/generic.cpp
new file mode 100644
index 0000000..d165d27
--- /dev/null
+++ b/generic.cpp
@@ -0,0 +1,56 @@
+/*
+ * PSX-Tools Bundle Pack
+ * Copyright (C) 2002 Nicolas "Pixel" Noble
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+
+char verbosity = 0;
+
+char * heads[] = {"EE", "--", "WW", "II"};
+
+void printm(int level, char * m, ...) {
+ va_list ap;
+
+ if (verbosity < level) {
+ return;
+ }
+
+ if (level >= 0) {
+ fprintf(stderr, "(%s) ", heads[level]);
+ }
+
+ va_start(ap, m);
+ vfprintf(stderr, m, ap);
+ va_end(ap);
+}
+
+char ** split(char * s, char t) {
+ static char * p[100];
+ int i;
+
+ for (i = 1, p[0] = s; *s; s++) {
+ if (*s == t) {
+ *s = 0;
+ p[i++] = s + 1;
+ }
+ }
+ p[i] = 0;
+
+ return p;
+}
diff --git a/generic.h b/generic.h
new file mode 100644
index 0000000..08fb7eb
--- /dev/null
+++ b/generic.h
@@ -0,0 +1,37 @@
+/*
+ * PSX-Tools Bundle Pack
+ * Copyright (C) 2002 Nicolas "Pixel" Noble
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __GENERIC_H__
+#define __GENERIC_H__
+
+#define M_BARE -1
+#define M_ERROR 0
+#define M_STATUS 1
+#define M_WARNING 2
+#define M_INFO 3
+
+#ifndef bcopy
+#define bcopy(x,y,z) memcpy((y),(x),(z))
+#endif
+
+extern char verbosity;
+void printm(int level, char * fmt, ...);
+char ** split(char * s, char t);
+
+#endif
diff --git a/info-cd.cpp b/info-cd.cpp
new file mode 100644
index 0000000..2ac872f
--- /dev/null
+++ b/info-cd.cpp
@@ -0,0 +1,40 @@
+/*
+ * PSX-Tools Bundle Pack
+ * Copyright (C) 2002 Nicolas "Pixel" Noble
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdio.h>
+#include "cdutils.h"
+
+int main(int argc, char ** argv) {
+ int h;
+ struct DirEntry dir;
+
+ h = open(argv[1], O_RDONLY);
+
+ show_iso_infos(h);
+ show_pt_infos(h);
+ show_head_entry();
+ show_dir(h, &rootDir);
+ show_head_entry();
+ dir = find_path(h, strdup("/BATTLE"));
+ show_dir(h, &dir);
+}
diff --git a/lz77 b/lz77
new file mode 100755
index 0000000..462d715
--- /dev/null
+++ b/lz77
Binary files differ
diff --git a/lz77.cpp b/lz77.cpp
new file mode 100644
index 0000000..4648964
--- /dev/null
+++ b/lz77.cpp
@@ -0,0 +1,757 @@
+/*
+ * PSX-Tools Bundle Pack
+ * Copyright (C) 2002 Nicolas "Pixel" Noble
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+#include <iostream.h>
+#include "fileutils.h"
+#include "generic.h"
+#include "lz77.h"
+
+int lz77_maxsize = 18;
+int lz77_maxptr = 0x0fff;
+int tolerate = 1;
+
+scheme_t schemes[] = {
+/* Nom 1 I J O N 16 Op F Lm1 Ls1 Lm2 Ls2 Jm1 Js1 Jm2 Js2 Fm1 Fs1 Fm2 Fs2 Vm1 Vs1 Vm2 Vs2 */
+ {"Xenogears", 1, 0, 0, 1, 0, 0, 0, 0, 0x00, 0, 0xf0, -4, 0xff, 0, 0x0f, 8, 0x00, 0, 0x00, 0, 0x00, 0, 0x00, 0},
+ {"DBZ RPG", 0, 0, 0, 0, 0, 0, 0, 0, 0x0f, 0, 0x00, 0, 0xf0, -4, 0xff, 4, 0x00, 0, 0x00, 0, 0x00, 0, 0x00, 0},
+ {"FF7", 0, 0, 0, 0, 0, 0, 0, 0, 0x00, 0, 0x0f, 0, 0xff, 0, 0xf0, 4, 0x00, 0, 0x00, 0, 0x00, 0, 0x00, 0},
+ {"Leen Mean", 1, 1, 1, 1, 0, 0, 0, 0, 0x0f, 0, 0x00, 0, 0xf0, 4, 0xff, 0, 0x00, 0, 0x00, 0, 0x00, 0, 0x00, 0},
+ {"Ogre Battle", 0, 0, 0, 1, 0, 0, 1, 0, 0xf8, -3, 0x00, 0, 0x07, 8, 0xff, 0, 0x00, 0, 0x00, 0, 0x00, 0, 0x00, 0},
+ {"Lodoss Wars", 0, 0, 0, 0, 0, 0, 0, 0, 0x00, 0, 0x7f, 0, 0xff, 0, 0x80, 1, 0x00, 0, 0x00, 0, 0x00, 0, 0x00, 0},
+ {"FF6 PSX", 0, 0, 0, 1, 1, 1, 0, 0, 0x1f, 1, 0x00, 0, 0xe0, -4, 0xff, 4, 0x00, 0, 0x00, 0, 0x00, 0, 0x00, 0},
+ {"Valkyrie-1", 0, 0, 0, 1, 1, 0, 0, 0, 0x00, 0, 0xf0, -4, 0xff, 0, 0x0f, 8, 0x00, 0, 0x00, 0, 0x00, 0, 0x00, 0},
+ {"Valkyrie-2", 0, 0, 0, 1, 1, 0, 0, 2, 0x00, 0, 0xf0, -4, 0xff, 0, 0x0f, 8, 0x00, 0, 0x0f, 0, 0xff, 0, 0x00, 0},
+ {0 , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00, 0, 0x00, 0, 0x00, 0, 0x00, 0}
+};
+
+scheme_t scheme = schemes[0];
+
+char swap_bits(char i) {
+ i = ((i >> 1) & 0x55) | ((i << 1) & 0xaa);
+ i = ((i >> 2) & 0x33) | ((i << 2) & 0xcc);
+ i = ((i >> 4) & 0x0f) | ((i << 4) & 0xf0);
+ return i;
+}
+
+unsigned int shift(unsigned int c, int s) {
+ return s > 0 ? (c << s) : c >> (-s);
+}
+
+void compute_limits(void) {
+ unsigned char val1, val2;
+
+ val1 = val2 = 0xff;
+
+ lz77_maxsize = shift(val1 & scheme.l_mask_1, scheme.l_shft_1) |
+ shift(val2 & scheme.l_mask_2, scheme.l_shft_2);
+ lz77_maxptr = shift(val1 & scheme.j_mask_1, scheme.j_shft_1) |
+ shift(val2 & scheme.j_mask_2, scheme.j_shft_2);
+
+ lz77_maxsize = lz77_maxsize + 3 + scheme.sixteen_bits;
+ lz77_maxptr += scheme.one_jump;
+
+ if (scheme.l_mask_1 & scheme.j_mask_1) {
+ printm(M_ERROR, "Masks are overlapping for value 1\n");
+ exit(-1);
+ }
+
+ if (scheme.l_mask_2 & scheme.j_mask_2) {
+ printm(M_ERROR, "Masks are overlapping for value 2\n");
+ exit(-1);
+ }
+
+ if (shift(scheme.l_mask_1, scheme.l_shft_1) & shift(scheme.l_mask_2, scheme.l_shft_2)) {
+ printm(M_ERROR, "Shifts build an overlap for lenght\n");
+ exit(-1);
+ }
+
+ if (shift(scheme.j_mask_1, scheme.j_shft_1) & shift(scheme.j_mask_2, scheme.j_shft_2)) {
+ printm(M_ERROR, "Shifts build an overlap for jump\n");
+ exit(-1);
+ }
+
+ printm(M_INFO, "Computed values: maxsize = %i, maxptr = 0x%06x\n", lz77_maxsize, lz77_maxptr);
+}
+
+unsigned long lz77_decomp(FILE * f_source, FILE * f_cible, long true_length)
+{
+ unsigned char bitmap, fbitmap;
+ unsigned char valeur;
+ unsigned char * text_buf;
+ unsigned char val1, val2, val3;
+ int negative_error = scheme.negative_trick, overlap_error = scheme.overlap_trick;
+ int r = 0;
+ int decomp_count;
+ int decomp_length;
+ int decomp_fill;
+ int decomp_jump;
+ int decomp_offset;
+ int loop_length;
+ int whole_count;
+ int i, j;
+ long length, reads;
+
+ compute_limits();
+
+ fread(&length, 1, 4, f_source);
+ if (true_length >= 0) {
+ length = true_length;
+ }
+ whole_count = 0;
+
+ printm(M_INFO, "Decompressing %i bytes\n", length);
+
+ text_buf = (unsigned char *) malloc(length + 8);
+
+ do {
+ fread(&bitmap, 1, 1, f_source);
+ if (scheme.sixteen_bits) {
+ fread(&fbitmap, 1, 1, f_source);
+ printm(M_INFO, "16bits behavior, false bitmap = %02x\n", fbitmap);
+ }
+ if (scheme.bitmap_inversed) {
+ bitmap = swap_bits(bitmap);
+ }
+ printm(M_INFO, "Begin of block, bitmap = %02x\n", bitmap);
+ for (i = 0; i < 8; i++) {
+ printm(M_INFO, " - Chunk %i (offset cible = %li = 0x%04x, offset source = %li = 0x%04x)\n", i, ftell(f_cible), ftell(f_cible), ftell(f_source), ftell(f_source));
+ if (whole_count >= length)
+ break;
+ if ((bitmap & 1) ^ scheme.one_is_compressed) {
+ for (j = 0; j < (scheme.sixteen_bits ? 2 : 1); j++) {
+ reads = fread(&valeur, 1, 1, f_source);
+ if (!reads) {
+ printm(M_WARNING, " WARNING! PADDING!\n");
+ free(text_buf);
+ return length;
+ }
+ printm(M_INFO, " Copying 0x%02x\n", valeur);
+ fwrite(&valeur, 1, 1, f_cible);
+ text_buf[r++] = valeur;
+ whole_count++;
+ }
+ } else {
+ fread(&val1, 1, 1, f_source);
+ fread(&val2, 1, 1, f_source);
+ decomp_length = shift(val1 & scheme.l_mask_1, scheme.l_shft_1) |
+ shift(val2 & scheme.l_mask_2, scheme.l_shft_2);
+ decomp_fill = shift(val1 & scheme.f_mask_1, scheme.f_shft_1) |
+ shift(val2 & scheme.f_mask_2, scheme.f_shft_2);
+ decomp_jump = shift(val1 & scheme.j_mask_1, scheme.j_shft_1) |
+ shift(val2 & scheme.j_mask_2, scheme.j_shft_2);
+ valeur = shift(val1 & scheme.v_mask_1, scheme.v_shft_1) |
+ shift(val2 & scheme.v_mask_2, scheme.v_shft_2);
+ decomp_jump &= lz77_maxptr;
+ decomp_jump += scheme.one_jump;
+ decomp_length = decomp_length + 3 + scheme.sixteen_bits;
+ decomp_fill = decomp_fill + 3 + scheme.sixteen_bits;
+ if ((decomp_length == lz77_maxsize) && (scheme.filling)) {
+ if ((decomp_fill == 3) && (scheme.filling == 2)) {
+ fread(&val3, 1, 1, f_source);
+ printm(M_INFO, " Found an extended needle (val1 = 0x%02x, val2 = 0x%02x, val3 = 0x%02x)\n", val1, val2, val3);
+ decomp_fill = val1 + 19;
+ valeur = val3;
+ } else {
+ printm(M_INFO, " Found a 0x%02x-filling needle of %li bytes (val1 = 0x%02x, val2 = 0x%02x)\n", valeur, decomp_fill, val1, val2);
+ }
+ for (decomp_count = 0; decomp_count < decomp_fill; decomp_count++) {
+ fwrite(&valeur, 1, 1, f_cible);
+ text_buf[r++] = valeur;
+ whole_count++;
+ }
+ } else {
+ if (scheme.opposite) {
+ decomp_offset = r - lz77_maxptr - 1 + decomp_jump;
+ } else {
+ decomp_offset = r - decomp_jump;
+ }
+ loop_length = decomp_offset + decomp_length;
+ if ((loop_length >= r) && (!overlap_error)) {
+ if (!tolerate) {
+ free(text_buf);
+ return 0;
+ }
+ printm(M_ERROR, "Overlap trick used without it beeing enabled in the scheme.\n");
+ overlap_error = 1;
+ }
+ printm(M_INFO, " Found a needle of %li bytes at %li = 0x%04x, jump of %li = 0x%04x (val1 = 0x%02x, val2 = 0x%02x)\n", decomp_length, decomp_offset, decomp_offset, decomp_jump, decomp_jump, val1, val2);
+ for (decomp_count = decomp_offset; decomp_count < loop_length; decomp_count++) {
+ if (decomp_count < 0) {
+ valeur = 0;
+ fwrite(&valeur, 1, 1, f_cible);
+ text_buf[r++] = 0;
+ whole_count++;
+ if (!negative_error) {
+ if (!tolerate) {
+ free(text_buf);
+ return 0;
+ }
+ printm(M_ERROR, "Negative trick used without it beeing enabled in the scheme.\n");
+ negative_error = 1;
+ }
+ printm(M_INFO, "Filling with 0\n");
+ } else {
+ fwrite(&text_buf[decomp_count], 1, 1, f_cible);
+ printm(M_INFO, "@0x%04x: 0x%02x\n", decomp_count, text_buf[decomp_count]);
+ text_buf[r++] = text_buf[decomp_count];
+ whole_count++;
+ }
+ if (whole_count >= length)
+ break;
+ }
+ }
+ }
+ bitmap >>= 1;
+ }
+ } while (whole_count < length);
+ free(text_buf);
+
+ return length;
+}
+
+unsigned char lz77_rd(unsigned char * t, long p) {
+ return ((p < 0) ? 0 : (t[p]));
+}
+
+long lz77_comp_strstr(unsigned char * needle, unsigned char * r, long * l, long sp) {
+ char redo[256];
+ long length, i, p, ptr, maxlength;
+
+ i = 1;
+ redo[0] = p = 0;
+ while (i < lz77_maxsize) {
+ if (needle[i] == needle[p]) {
+ redo[i++] = ++p;
+ } else if (p > 0) {
+ p = redo[p - 1];
+ } else {
+ redo[i++] = 0;
+ }
+ }
+
+ length = maxlength = 0;
+ i = sp;
+ p = 0;
+ ptr = 0;
+
+ while ((i - sp - (scheme.overlap_trick ? p : 0)) < *l) {
+ if (needle[p] == lz77_rd(r, i)) {
+ if (p == (lz77_maxsize - 1)) {
+ *l = lz77_maxsize;
+ return i - lz77_maxsize + 1;
+ }
+ i++;
+ p++;
+ } else if (p > 0) {
+ if (p > maxlength) {
+ if (!((i - p) & scheme.sixteen_bits)) {
+ ptr = i - (maxlength = p);
+ }
+ }
+ p = redo[p - 1];
+ } else {
+ i++;
+ }
+ }
+
+ *l = maxlength;
+ return ptr;
+}
+
+unsigned char * lz77_memcomp(unsigned char * r, long * l, long * delta) {
+ unsigned char bitmap, * comp, bitmap_count;
+ long ptr, needle, needle_length, comp_ptr, bitmap_ptr, blk = 0, val1, val2;
+ long jump, farest, remaining;
+ int j;
+
+ comp = (unsigned char *) malloc(3 * *l);
+
+ compute_limits();
+
+ ptr = 0;
+ bitmap_count = 0;
+ comp_ptr = 1 + scheme.sixteen_bits;
+ bitmap = 0;
+ bitmap_ptr = 0;
+ printm(M_INFO, "Begin of block 0.\n");
+ while ((remaining = *l - ptr) > 0) {
+ printm(M_INFO, " Remaining bytes: %li\n", remaining);
+ bitmap_count++;
+ bitmap >>= 1;
+ farest = ptr - lz77_maxptr;
+ farest = farest > ((-lz77_maxsize) * scheme.negative_trick) ? farest : -lz77_maxsize * scheme.negative_trick;
+ needle_length = ptr - farest;
+ needle = lz77_comp_strstr(&r[ptr], r, &needle_length, farest);
+ if ((needle < 0) && ((-needle) > needle_length)) {
+ needle = -needle_length;
+ }
+ printm(M_INFO, " - Chunk %i (offset source = %li = 0x%04x, offset cible = %li = 0x%04x)\n", bitmap_count - 1, ptr, ptr, comp_ptr, comp_ptr);
+ jump = ptr - needle;
+ needle_length = needle_length > remaining ? remaining : needle_length;
+
+ if (needle_length & scheme.sixteen_bits) {
+ needle_length--;
+ }
+
+ if ((needle < 0) || (!jump)) {
+ printm(M_INFO, " Nothing found.\n");
+ } else {
+ printm(M_INFO, " Found a needle of %i bytes at offset %i (jump = %i = 0x%04x)\n", needle_length, needle, jump, jump);
+ }
+
+ if ((needle_length <= (2 + scheme.sixteen_bits)) || (jump > lz77_maxptr) || (!jump)) {
+ if (needle_length > 2) {
+ printm(M_ERROR, " ** REJECTED **\n");
+ }
+ for (j = 0; j < (scheme.sixteen_bits ? 2 : 1); j++) {
+ printm(M_INFO, " Repeating 0x%02x\n", r[ptr]);
+ comp[comp_ptr] = r[ptr];
+ ptr++;
+ comp_ptr++;
+ }
+ bitmap |= 0x80;
+ } else {
+ int j;
+ printm(M_INFO, " Found a needle of %li bytes at %li = 0x%04x\n", needle_length, needle, needle);
+ for (j = 0; j < needle_length; j++) {
+ printm(M_INFO, "@0x%04x: 0x%02x - @0x%04x: 0x%02x\n", needle + j, lz77_rd(r, needle + j), ptr + j, lz77_rd(r, ptr + j));
+ if (lz77_rd(r, needle + j) != lz77_rd(r, ptr + j)) {
+ printm(M_ERROR, "ERROR!!\n");
+ }
+ }
+ printm(M_INFO, "ptr = %li, needle = %li, jump = %li = 0x%03x\n", ptr, needle, jump, jump);
+ ptr += needle_length;
+ needle_length -= 3;
+ jump -= scheme.one_jump;
+ if (scheme.opposite) {
+ jump = lz77_maxptr + 1 - jump;
+ }
+ val1 = comp[comp_ptr++] = (shift(jump, -scheme.j_shft_1) & scheme.j_mask_1) |
+ (shift(needle_length, -scheme.l_shft_1) & scheme.l_mask_1);
+ val2 = comp[comp_ptr++] = (shift(jump, -scheme.j_shft_2) & scheme.j_mask_2) |
+ (shift(needle_length, -scheme.l_shft_2) & scheme.l_mask_2);
+ printm(M_INFO, " writing info1 = 0x%02x, info2 = 0x%02x\n", val1, val2);
+ }
+
+ bitmap ^= scheme.one_is_compressed << 7;
+
+ if (bitmap_count == 8) {
+ blk++;
+ printm(M_INFO, "End of block, writing bitmap = 0x%02x\n", bitmap);
+ printm(M_INFO, "Begin of block %li.\n", blk);
+ bitmap_count = 0;
+ if (scheme.bitmap_inversed)
+ bitmap = swap_bits(bitmap);
+ comp[bitmap_ptr] = bitmap;
+ if (scheme.sixteen_bits) {
+ comp[bitmap_ptr + 1] = 0;
+ }
+ bitmap_ptr = comp_ptr;
+ comp_ptr += (scheme.sixteen_bits ? 2 : 1);
+ }
+ }
+
+ if (bitmap_count) {
+ bitmap >>= (8 - bitmap_count);
+ if (scheme.bitmap_inversed)
+ bitmap = swap_bits(bitmap);
+ comp[bitmap_ptr] = bitmap;
+ if (scheme.sixteen_bits) {
+ comp[bitmap_ptr + 1] = 0;
+ }
+ } else {
+ comp_ptr--;
+ }
+
+ if (delta) {
+ *delta = (bitmap_count ? 8 - bitmap_count : 0);
+ }
+
+ *l = comp_ptr;
+ return comp;
+}
+
+void lz77_comp(FILE * f_source, FILE * f_cible, long * delta) {
+ long length = filesize(f_source), l;
+ unsigned char * r = (unsigned char *) malloc(length), * c;
+
+ fread(r, 1, length, f_source);
+ l = length;
+ c = lz77_memcomp(r, &l, delta);
+ if (delta) {
+ length += *delta;
+ }
+ fwrite(&length, 1, 4, f_cible);
+ if (delta) {
+ length -= *delta;
+ }
+ fwrite(c, 1, l, f_cible);
+ free(c);
+ free(r);
+}
+
+#ifdef LZ77_MAIN
+
+char * fn1, * fn2, * pname;
+
+int lga = 0;
+int compress = 1;
+
+struct option long_options[] = {
+ {"1iscomp", 1, &lga, 1 },
+ {"overlap", 1, &lga, 2 },
+ {"16bits", 1, &lga, 11 },
+ {"negative", 1, &lga, 12 },
+ {"opposite", 1, &lga, 13 },
+ {"filling", 1, &lga, 14 },
+ {"inverse", 1, &lga, 23 },
+ {"onejump", 1, &lga, 24 },
+ {"lmask1", 1, &lga, 3 },
+ {"lshft1", 1, &lga, 4 },
+ {"lmask2", 1, &lga, 5 },
+ {"lshft2", 1, &lga, 6 },
+ {"jmask1", 1, &lga, 7 },
+ {"jshft1", 1, &lga, 8 },
+ {"jmask2", 1, &lga, 9 },
+ {"jshft2", 1, &lga, 10 },
+ {"fmask1", 1, &lga, 15 },
+ {"fshft1", 1, &lga, 16 },
+ {"fmask2", 1, &lga, 17 },
+ {"fshft2", 1, &lga, 18 },
+ {"vmask1", 1, &lga, 19 },
+ {"vshft1", 1, &lga, 20 },
+ {"vmask2", 1, &lga, 21 },
+ {"vshft2", 1, &lga, 22 },
+ {"help", 0, NULL, 'h'},
+ {"scheme", 1, NULL, 's'},
+ {"length", 1, NULL, 'l'},
+ {"version", 0, NULL, 'V'},
+ {"verbose", 0, NULL, 'v'},
+ {"show", 0, NULL, 'S'},
+ {"dump", 0, NULL, 'D'},
+ {"compress", 0, NULL, 'c'},
+ {"decompress", 0, NULL, 'd'},
+ {0, 0, NULL, 0 }
+};
+
+void showhelp(void) {
+ printm(M_BARE,
+"Usages:\n"
+" %s <--help|-h|-H|-?> Show this help and exit.\n"
+" %s <--dump> Show the built-in schemes and exit.\n"
+" %s <--version|-V> Show the version and copyrights and exit.\n"
+" %s [-c|-d] [-s <scheme>] [-l <length>] [-S] [-v] <infile> <outfile>\n"
+"\n"
+"-c --compress Compress <infile> to <outfile>\n"
+"-d --decompress Decompress <infile> to <outfile>\n"
+"-s <scheme> --scheme=<scheme> Loads the built-in scheme number <scheme>\n"
+"-l <length> --length=<length> Specify the true length for decompression,\n"
+" or enable the padding behavior for compression.\n"
+"-S --show Show the actual scheme before processing.\n"
+"-v --verbose Display a *LOT* of informations.\n"
+"\n"
+"Additionnaly you have the scheme manipulation options:\n"
+"--1iscomp --overlap --negative --16bits --filling --inverse --onejump\n"
+"--lmask1 --lshft1 --lmask2 --lshft2 --jmask1 --jshft1 --jmask2 --jshft2\n"
+"--vmask1 --vshft1 --vmask2 --vshft2 --fmask1 --fshft1 --fmask2 --fshft2\n"
+"\n"
+"If you don't know what they are, forget them.\n"
+"\n"
+"Default behavior is to %scompress.\n"
+"\n", pname, pname, pname, pname, compress ? "" : "de");
+}
+
+void showscheme(void) {
+ printm(M_BARE,
+"Actual scheme:\n"
+"--1iscomp %i\n"
+"--overlap %i\n"
+"--negative %i\n"
+"--16bits %i\n"
+"--opposite %i\n"
+"--filling %i\n"
+"--inverse %i\n"
+"--onejump %i\n"
+"--lmask1 0x%02x\n"
+"--lshft1 %i\n"
+"--lmask2 0x%02x\n"
+"--lshft2 %i\n"
+"--jmask1 0x%02x\n"
+"--jshft1 %i\n"
+"--jmask2 0x%02x\n"
+"--jshft2 %i\n"
+"--fmask1 0x%02x\n"
+"--fshft1 %i\n"
+"--fmask2 0x%02x\n"
+"--fshft2 %i\n"
+"--vmask1 0x%02x\n"
+"--vshft1 %i\n"
+"--vmask2 0x%02x\n"
+"--vshft2 %i\n"
+"\n", scheme.one_is_compressed, scheme.overlap_trick, scheme.negative_trick, scheme.sixteen_bits,
+scheme.opposite, scheme.filling, scheme.bitmap_inversed, scheme.one_jump,
+scheme.l_mask_1, scheme.l_shft_1, scheme.l_mask_2, scheme.l_shft_2,
+scheme.j_mask_1, scheme.j_shft_1, scheme.j_mask_2, scheme.j_shft_2,
+scheme.f_mask_1, scheme.f_shft_1, scheme.f_mask_2, scheme.f_shft_2,
+scheme.v_mask_1, scheme.v_shft_1, scheme.v_mask_2, scheme.v_shft_2);
+}
+
+void dump(void) {
+ int i;
+
+ printm(M_BARE, "Built-in schemes:\n");
+ for (i = 0; schemes[i].name; i++) {
+ printm(M_BARE, "%2i - %s\n", i, schemes[i].name);
+ }
+}
+
+int main(int argc, char ** argv) {
+ long length = -1;
+ FILE * f1, * f2;
+ int p, show = 0;
+ int c, s, t;
+
+ pname = strdup(argv[0]);
+ p = strlen(pname) - 5;
+
+ verbosity = M_STATUS;
+
+ if (!strcasecmp(pname + p, "dlz77")) {
+ compress = 0;
+ }
+
+ printm(M_BARE,
+LZ77_NAME " compressor/decompressor version " LZ77_VERSION ",\n"
+"Copyright (C) 2002 Nicolas \"Pixel\" Noble\n"
+"This software comes with ABSOLUTELY NO WARRANTY; see COPYING for details\n"
+"Thanks to Czar Dragon, for his little 'LZ77' schemes FAQ.\n"
+"Special thanks to Yazoo, who taught me PSX hacking.\n"
+"\n");
+
+ while ((c = getopt_long(argc, argv, "Hhs:l:vVScd", long_options, NULL)) != EOF) {
+ switch (c) {
+ case 0:
+ switch (lga) {
+ case 1:
+ t = atoi(optarg);
+ if ((t != 1) && (t != 0)) {
+ printm(M_ERROR, "Invalid value for boolean: %s\n", optarg);
+ } else {
+ scheme.one_is_compressed = t;
+ }
+ break;
+ case 2:
+ t = atoi(optarg);
+ if ((t != 1) && (t != 0)) {
+ printm(M_ERROR, "Invalid value for boolean: %s\n", optarg);
+ } else {
+ scheme.overlap_trick = t;
+ }
+ break;
+ case 3:
+ sscanf(optarg, "%i", &scheme.l_mask_1);
+ break;
+ case 4:
+ scheme.l_shft_1 = atoi(optarg);
+ break;
+ case 5:
+ sscanf(optarg, "%i", &scheme.l_mask_2);
+ break;
+ case 6:
+ scheme.l_shft_2 = atoi(optarg);
+ break;
+ case 7:
+ sscanf(optarg, "%i", &scheme.j_mask_1);
+ break;
+ case 8:
+ scheme.j_shft_1 = atoi(optarg);
+ break;
+ case 9:
+ sscanf(optarg, "%i", &scheme.j_mask_2);
+ break;
+ case 10:
+ scheme.j_mask_2 = atoi(optarg);
+ break;
+ case 11:
+ t = atoi(optarg);
+ if ((t != 1) && (t != 0)) {
+ printm(M_ERROR, "Invalid value for boolean: %s\n", optarg);
+ } else {
+ scheme.sixteen_bits = t;
+ }
+ break;
+ case 12:
+ t = atoi(optarg);
+ if ((t != 1) && (t != 0)) {
+ printm(M_ERROR, "Invalid value for boolean: %s\n", optarg);
+ } else {
+ scheme.negative_trick = t;
+ }
+ break;
+ case 13:
+ t = atoi(optarg);
+ if ((t != 1) && (t != 0)) {
+ printm(M_ERROR, "Invalid value for boolean: %s\n", optarg);
+ } else {
+ scheme.opposite = t;
+ }
+ break;
+ case 14:
+ t = atoi(optarg);
+ if ((t != 2) && (t != 1) && (t != 0)) {
+ printm(M_ERROR, "Invalid value for ter: %s\n", optarg);
+ } else {
+ scheme.filling = t;
+ }
+ break;
+ case 15:
+ sscanf(optarg, "%i", &scheme.f_mask_1);
+ break;
+ case 16:
+ scheme.f_shft_1 = atoi(optarg);
+ break;
+ case 17:
+ sscanf(optarg, "%i", &scheme.f_mask_2);
+ break;
+ case 18:
+ scheme.f_shft_2 = atoi(optarg);
+ break;
+ case 19:
+ sscanf(optarg, "%i", &scheme.v_mask_1);
+ break;
+ case 20:
+ scheme.v_shft_1 = atoi(optarg);
+ break;
+ case 21:
+ sscanf(optarg, "%i", &scheme.v_mask_2);
+ break;
+ case 22:
+ scheme.v_mask_2 = atoi(optarg);
+ break;
+ case 23:
+ t = atoi(optarg);
+ if ((t != 1) && (t != 0)) {
+ printm(M_ERROR, "Invalid value for boolean: %s\n", optarg);
+ } else {
+ scheme.bitmap_inversed = t;
+ }
+ break;
+ case 24:
+ t = atoi(optarg);
+ if ((t != 1) && (t != 0)) {
+ printm(M_ERROR, "Invalid value for boolean: %s\n", optarg);
+ } else {
+ scheme.one_jump = t;
+ }
+ break;
+ default:
+ showhelp();
+ printm(M_ERROR, "Unknow option.\n");
+ exit(-1);
+ }
+ break;
+ case '?':
+ case 'H':
+ case 'h':
+ showhelp();
+ exit(0);
+ case 's':
+ s = atoi(optarg);
+ scheme = schemes[s];
+ break;
+ case 'l':
+ length = atoi(optarg);
+ break;
+ case 'v':
+ verbosity = M_INFO;
+ break;
+ case 'V':
+ exit(0);
+ case 'S':
+ show = 1;
+ break;
+ case 'D':
+ dump();
+ exit(0);
+ break;
+ case 'd':
+ compress = 0;
+ break;
+ case 'c':
+ compress = 1;
+ break;
+ default:
+ showhelp();
+ printm(M_ERROR, "Unknow option.\n");
+ exit(-1);
+ }
+ }
+
+ if (show) showscheme();
+
+ if (optind != (argc - 2)) {
+ if (optind > (argc - 2)) {
+ printm(M_ERROR, "Not enough filenames\n");
+ exit(-1);
+ } else {
+ printm(M_ERROR, "Too much arguments\n");
+ exit(-1);
+ }
+ }
+
+ fn1 = argv[optind++];
+ fn2 = argv[optind++];
+
+ if (!(f1 = fopen(fn1, "r"))) {
+ printm(M_ERROR, "Error opening file %s for reading.\n", fn1);
+ }
+
+ if (!(f2 = fopen(fn2, "w"))) {
+ printm(M_ERROR, "Error opening file %s for writing.\n", fn2);
+ }
+
+ if (compress) {
+ printm(M_STATUS, "Compressing `%s' to `%s'...\n", fn1, fn2);
+ } else {
+ printm(M_STATUS, "Decompressing `%s' to `%s'...\n", fn1, fn2);
+ }
+
+ if (compress) {
+ if (length == -1) {
+ lz77_comp(f1, f2);
+ } else {
+ lz77_comp(f1, f2, &length);
+ }
+ } else {
+ length = lz77_decomp(f1, f2, length);
+ }
+
+ printm(M_STATUS, "Done, filesize changed from %i to %i.\n", filesize(f1), filesize(f2));
+
+ fclose(f1);
+ fclose(f2);
+
+ exit(0);
+}
+
+#endif
diff --git a/lz77.h b/lz77.h
new file mode 100644
index 0000000..4158cd4
--- /dev/null
+++ b/lz77.h
@@ -0,0 +1,60 @@
+/*
+ * PSX-Tools Bundle Pack
+ * Copyright (C) 2002 Nicolas "Pixel" Noble
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __LZ77_H__
+#define __lZ77_H__
+
+#include <stdio.h>
+#include <generic.h>
+
+#define LZ77_VERSION "3.0.0-pre1"
+#define LZ77_NAME "LZ77"
+
+typedef struct {
+ char * name;
+ int one_is_compressed, bitmap_inversed, one_jump, overlap_trick, negative_trick, sixteen_bits, opposite, filling;
+ int l_mask_1, l_shft_1, l_mask_2, l_shft_2;
+ int j_mask_1, j_shft_1, j_mask_2, j_shft_2;
+ int f_mask_1, f_shft_1, f_mask_2, f_shft_2;
+ int v_mask_1, v_shft_1, v_mask_2, v_shft_2;
+} scheme_t;
+
+enum {
+ XENO = 0,
+ DBZ,
+ FF7,
+ LM,
+ OB,
+ LODOSS,
+ FF6,
+ VP_1,
+ VP_2,
+ END
+};
+
+extern scheme_t scheme, schemes[];
+
+extern int tolerate;
+
+unsigned long lz77_decomp(FILE * f_source, FILE * f_cible, long true_length = -1);
+void lz77_comp(FILE * f_source, FILE * f_cible, long * delta = NULL);
+
+char swap_bits(char);
+
+#endif
diff --git a/yazedc b/yazedc
new file mode 100755
index 0000000..c12dda3
--- /dev/null
+++ b/yazedc
Binary files differ
diff --git a/yazedc.cpp b/yazedc.cpp
new file mode 100644
index 0000000..9d5b838
--- /dev/null
+++ b/yazedc.cpp
@@ -0,0 +1,1017 @@
+/*
+ * PSX-Tools Bundle Pack
+ * Copyright (C) 1998 Heiko Eissfeldt
+ * portions used& Chris Smith
+ * Modified by Yazoo, then by
+ * Nicolas "Pixel" Noble
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define RS_L12_BITS 8
+
+/* audio sector definitions for CIRC */
+#define FRAMES_PER_SECTOR 98
+/* user data bytes per frame */
+#define L1_RAW 24
+/* parity bytes with 8 bit */
+#define L1_Q 4
+#define L1_P 4
+
+/* audio sector Cross Interleaved Reed-Solomon Code (CIRC) encoder (layer 1) */
+/* adds P- and Q- parity information to audio (f2) frames. Also
+ optionally handles the various delays and permutations. The output with all
+ stages enabled can be fed into the Eight-Fourteen-Modulator.
+ On input: 2352 bytes of audio data is given.
+ On output: 3136 bytes of CIRC enriched audio data are returned.
+ */
+int do_encode_L1(unsigned char in[L1_RAW*FRAMES_PER_SECTOR],
+ unsigned char out[(L1_RAW+L1_Q+L1_P)*FRAMES_PER_SECTOR],
+ int delay1, int delay2, int delay3, int scramble);
+
+/* data sector definitions for RSPC */
+/* user data bytes per frame */
+#define L2_RAW (1024*2)
+/* parity bytes for 16 bit units */
+#define L2_Q (26*2*2)
+#define L2_P (43*2*2)
+
+/* known sector types */
+#define MODE_0 0
+#define MODE_1 1
+#define MODE_2 2
+#define MODE_2_FORM_1 3
+#define MODE_2_FORM_2 4
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* set one of the MODE_* constants for subsequent data sector formatting */
+int set_sector_type(int st);
+/* get the current sector type setting for data sector formatting */
+int get_sector_type(void);
+
+/* data sector layer 2 Reed-Solomon Product Code encoder */
+/* encode the given data portion depending on sector type (see
+ get/set_sector_type() functions). Use the given address for the header.
+ The returned data is __unscrambled__ and not in F2-frame format (for that
+ see function scramble_L2()).
+ Supported sector types:
+ MODE_0: a 12-byte sync field, a header and 2336 zeros are returned.
+ MODE_1: the user data portion (2048 bytes) has to be given
+ at offset 16 in the inout array.
+ Sync-, header-, edc-, spare-, p- and q- fields will be added.
+ MODE_2: the user data portion (2336 bytes) has to be given
+ at offset 16 in the inout array.
+ Sync- and header- fields will be added.
+ MODE_2_FORM_1: the user data portion (8 bytes subheader followed
+ by 2048 bytes data) has to be given at offset 16
+ in the inout array.
+ Sync-, header-, edc-, p- and q- fields will be added.
+ MODE_2_FORM_2: the user data portion (8 bytes subheader followed
+ by 2324 bytes data) has to be given at offset 16
+ in the inout array.
+ Sync-, header- and edc- fields will be added.
+*/
+int do_encode_L2(unsigned char *inout, int sectortype, unsigned address);
+int decode_L2_Q(unsigned char inout[4 + L2_RAW + 12 + L2_Q]);
+int decode_L2_P(unsigned char inout[4 + L2_RAW + 12 + L2_Q + L2_P]);
+unsigned long int build_edc(unsigned char inout[], int from, int upto);
+
+/* generates f2 frames from otherwise fully formatted sectors (generated by
+ do_encode_L2()). */
+int scramble_L2(unsigned char *inout);
+
+#ifdef __cplusplus
+}
+#endif
+
+/* r-w sub channel definitions */
+#define RS_SUB_RW_BITS 6
+
+#define PACKETS_PER_SUBCHANNELFRAME 4
+#define LSUB_RAW 18
+#define LSUB_QRAW 2
+/* 6 bit */
+#define LSUB_Q 2
+#define LSUB_P 4
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* R-W subchannel encoder */
+/* On input: 72 bytes packed user data, four frames with each 18 bytes.
+ On output: per frame: 2 bytes user data, 2 bytes Q parity,
+ 16 bytes user data, 4 bytes P parity.
+ Options:
+ delay1: use low level delay line
+ scramble: perform low level permutations
+ */
+int do_encode_sub(unsigned char in[LSUB_RAW*PACKETS_PER_SUBCHANNELFRAME],
+ unsigned char out[(LSUB_RAW+LSUB_Q+LSUB_P)*PACKETS_PER_SUBCHANNELFRAME],
+ int delay1, int scramble);
+int do_decode_sub(unsigned char in[(LSUB_RAW+LSUB_Q+LSUB_P)*PACKETS_PER_SUBCHANNELFRAME],
+ unsigned char out[LSUB_RAW*PACKETS_PER_SUBCHANNELFRAME],
+ int delay1, int scramble);
+
+int decode_LSUB_Q(unsigned char inout[LSUB_QRAW + LSUB_Q]);
+int decode_LSUB_P(unsigned char inout[LSUB_RAW + LSUB_Q + LSUB_P]);
+
+#ifdef __cplusplus
+}
+#endif
+
+unsigned char minute, second, frame;
+
+/* these prototypes will become public when the function are implemented */
+#ifdef MAIN
+static int do_decode_L2(unsigned char in[(L2_RAW+L2_Q+L2_P)],
+ unsigned char out[L2_RAW]);
+static int do_decode_L1(unsigned char in[(L1_RAW+L1_Q+L1_P)*FRAMES_PER_SECTOR],
+ unsigned char out[L1_RAW*FRAMES_PER_SECTOR],
+ int delay1, int delay2, int delay3, int scramble);
+#endif
+
+/* ------------- tables generated by gen_encodes --------------*/
+
+#include "crctables"
+
+static int encode_L1_Q(unsigned char inout[L1_RAW + L1_Q])
+{
+ unsigned char *Q;
+ int i;
+
+ memmove(inout+L1_RAW/2+L1_Q, inout+L1_RAW/2, L1_RAW/2);
+ Q = inout + L1_RAW/2;
+
+ memset(Q, 0, L1_Q);
+ for (i = 0; i < L1_RAW + L1_Q; i++) {
+ unsigned char data;
+
+ if (i == L1_RAW/2) i += L1_Q;
+ data = inout[i];
+ if (data != 0) {
+ unsigned char base = rs_l12_log[data];
+
+ Q[0] ^= rs_l12_alog[(base+AQ[0][i]) % ((1 << RS_L12_BITS)-1)];
+ Q[1] ^= rs_l12_alog[(base+AQ[1][i]) % ((1 << RS_L12_BITS)-1)];
+ Q[2] ^= rs_l12_alog[(base+AQ[2][i]) % ((1 << RS_L12_BITS)-1)];
+ Q[3] ^= rs_l12_alog[(base+AQ[3][i]) % ((1 << RS_L12_BITS)-1)];
+ }
+ }
+
+ return 0;
+}
+static int encode_L1_P(unsigned char inout[L1_RAW + L1_Q + L1_P])
+{
+ unsigned char *P;
+ int i;
+
+ P = inout + L1_RAW + L1_Q;
+
+ memset(P, 0, L1_P);
+ for (i = 0; i < L2_RAW + L2_Q + L2_P; i++) {
+ unsigned char data;
+
+ data = inout[i];
+ if (data != 0) {
+ unsigned char base = rs_l12_log[data];
+
+ P[0] ^= rs_l12_alog[(base+AP[0][i]) % ((1 << RS_L12_BITS)-1)];
+ P[1] ^= rs_l12_alog[(base+AP[1][i]) % ((1 << RS_L12_BITS)-1)];
+ P[2] ^= rs_l12_alog[(base+AP[2][i]) % ((1 << RS_L12_BITS)-1)];
+ P[3] ^= rs_l12_alog[(base+AP[3][i]) % ((1 << RS_L12_BITS)-1)];
+ }
+ }
+ return 0;
+}
+
+#ifdef MAIN
+static int decode_L1_Q(unsigned char inout[L1_RAW + L1_Q])
+{
+ return 0;
+}
+
+static int decode_L1_P(unsigned char in[L1_RAW + L1_Q + L1_P])
+{
+ return 0;
+}
+#endif
+
+static int encode_L2_Q(unsigned char inout[4 + L2_RAW + 4 + 8 + L2_P + L2_Q])
+{
+ unsigned char *Q;
+ int i,j;
+
+ Q = inout + 4 + L2_RAW + 4 + 8 + L2_P;
+ memset(Q, 0, L2_Q);
+ for (j = 0; j < 26; j++) {
+ for (i = 0; i < 43; i++) {
+ unsigned char data;
+
+ /* LSB */
+ data = inout[(j*43*2+i*2*44) % (4 + L2_RAW + 4 + 8 + L2_P)];
+ if (data != 0) {
+ unsigned int base = rs_l12_log[data];
+
+ unsigned int sum = base + DQ[0][i];
+ if (sum >= ((1 << RS_L12_BITS)-1))
+ sum -= (1 << RS_L12_BITS)-1;
+
+ Q[0] ^= rs_l12_alog[sum];
+
+ sum = base + DQ[1][i];
+ if (sum >= ((1 << RS_L12_BITS)-1))
+ sum -= (1 << RS_L12_BITS)-1;
+
+ Q[26*2] ^= rs_l12_alog[sum];
+ }
+ /* MSB */
+ data = inout[(j*43*2+i*2*44+1) % (4 + L2_RAW + 4 + 8 + L2_P)];
+ if (data != 0) {
+ unsigned int base = rs_l12_log[data];
+
+ unsigned int sum = base+DQ[0][i];
+ if (sum >= ((1 << RS_L12_BITS)-1))
+ sum -= (1 << RS_L12_BITS)-1;
+
+ Q[1] ^= rs_l12_alog[sum];
+
+ sum = base + DQ[1][i];
+ if (sum >= ((1 << RS_L12_BITS)-1))
+ sum -= (1 << RS_L12_BITS)-1;
+
+ Q[26*2+1] ^= rs_l12_alog[sum];
+ }
+ }
+ Q += 2;
+ }
+ return 0;
+}
+
+static int encode_L2_P(unsigned char inout[4 + L2_RAW + 4 + 8 + L2_P])
+{
+ unsigned char *P;
+ int i,j;
+
+ P = inout + 4 + L2_RAW + 4 + 8;
+ memset(P, 0, L2_P);
+ for (j = 0; j < 43; j++) {
+ for (i = 0; i < 24; i++) {
+ unsigned char data;
+
+ /* LSB */
+ data = inout[i*2*43];
+ if (data != 0) {
+ unsigned int base = rs_l12_log[data];
+
+ unsigned int sum = base + DP[0][i];
+ if (sum >= ((1 << RS_L12_BITS)-1))
+ sum -= (1 << RS_L12_BITS)-1;
+
+ P[0] ^= rs_l12_alog[sum];
+
+ sum = base + DP[1][i];
+ if (sum >= ((1 << RS_L12_BITS)-1))
+ sum -= (1 << RS_L12_BITS)-1;
+
+ P[43*2] ^= rs_l12_alog[sum];
+ }
+ /* MSB */
+ data = inout[i*2*43+1];
+ if (data != 0) {
+ unsigned int base = rs_l12_log[data];
+
+ unsigned int sum = base + DP[0][i];
+ if (sum >= ((1 << RS_L12_BITS)-1))
+ sum -= (1 << RS_L12_BITS)-1;
+
+ P[1] ^= rs_l12_alog[sum];
+
+ sum = base + DP[1][i];
+ if (sum >= ((1 << RS_L12_BITS)-1))
+ sum -= (1 << RS_L12_BITS)-1;
+
+ P[43*2+1] ^= rs_l12_alog[sum];
+ }
+ }
+ P += 2;
+ inout += 2;
+ }
+ return 0;
+}
+
+int decode_L2_Q(unsigned char inout[4 + L2_RAW + 12 + L2_Q])
+{
+ return 0;
+}
+int decode_L2_P(unsigned char inout[4 + L2_RAW + 12 + L2_Q + L2_P])
+{
+ return 0;
+}
+
+int scramble_L2(unsigned char *inout)
+{
+ unsigned char *r = inout + 12;
+ unsigned char *s = yellowbook_scrambler;
+ unsigned int i;
+ unsigned int *f = (unsigned int *)inout;
+
+ for (i = (L2_RAW + L2_Q + L2_P +16)/sizeof(unsigned char); i; i--) {
+ *r++ ^= *s++;
+ }
+
+ /* generate F1 frames */
+ for (i = (2352/sizeof(unsigned int)); i; i--) {
+ *f++ = ((*f & 0xff00ff00UL) >> 8) | ((*f & 0x00ff00ffUL) << 8);
+ }
+
+ return 0;
+}
+
+static int encode_LSUB_Q(unsigned char inout[LSUB_RAW + LSUB_Q])
+{
+ unsigned char *Q;
+/* unsigned char data; */
+ int i;
+
+ memmove(inout+LSUB_QRAW+LSUB_Q, inout+LSUB_QRAW, LSUB_RAW-LSUB_QRAW);
+ Q = inout + LSUB_QRAW;
+
+ memset(Q, 0, LSUB_Q);
+
+#if 0
+ data = inout[0] & 0x3f;
+ if (data != 0) {
+ unsigned char base = rs_sub_rw_log[data];
+
+ Q[0] ^= rs_sub_rw_alog[(base+26) % ((1 << RS_SUB_RW_BITS)-1)];
+ Q[1] ^= rs_sub_rw_alog[(base+7) % ((1 << RS_SUB_RW_BITS)-1)];
+ }
+ data = inout[1] & 0x3f;
+ if (data != 0) {
+ unsigned char base = rs_sub_rw_log[data];
+
+ Q[0] ^= rs_sub_rw_alog[(base+6) % ((1 << RS_SUB_RW_BITS)-1)];
+ Q[1] ^= rs_sub_rw_alog[(base+1) % ((1 << RS_SUB_RW_BITS)-1)];
+ }
+#else
+ for (i = 0; i < LSUB_QRAW; i++) {
+ unsigned char data;
+
+ data = inout[i] & 0x3f;
+ if (data != 0) {
+ unsigned char base = rs_sub_rw_log[data];
+
+ Q[0] ^= rs_sub_rw_alog[(base+SQ[0][i]) % ((1 << RS_SUB_RW_BITS)-1)];
+ Q[1] ^= rs_sub_rw_alog[(base+SQ[1][i]) % ((1 << RS_SUB_RW_BITS)-1)];
+ }
+ }
+#endif
+ return 0;
+}
+
+
+static int encode_LSUB_P(unsigned char inout[LSUB_RAW + LSUB_Q + LSUB_P])
+{
+ unsigned char *P;
+ int i;
+
+ P = inout + LSUB_RAW + LSUB_Q;
+
+ memset(P, 0, LSUB_P);
+ for (i = 0; i < LSUB_RAW + LSUB_Q; i++) {
+ unsigned char data;
+
+ data = inout[i] & 0x3f;
+ if (data != 0) {
+ unsigned char base = rs_sub_rw_log[data];
+
+ P[0] ^= rs_sub_rw_alog[(base+SP[0][i]) % ((1 << RS_SUB_RW_BITS)-1)];
+ P[1] ^= rs_sub_rw_alog[(base+SP[1][i]) % ((1 << RS_SUB_RW_BITS)-1)];
+ P[2] ^= rs_sub_rw_alog[(base+SP[2][i]) % ((1 << RS_SUB_RW_BITS)-1)];
+ P[3] ^= rs_sub_rw_alog[(base+SP[3][i]) % ((1 << RS_SUB_RW_BITS)-1)];
+ }
+ }
+ return 0;
+}
+
+int decode_LSUB_Q(unsigned char inout[LSUB_QRAW + LSUB_Q])
+{
+ unsigned char Q[LSUB_Q];
+ int i;
+
+ memset(Q, 0, LSUB_Q);
+ for (i = LSUB_QRAW + LSUB_Q -1; i>=0; i--) {
+ unsigned char data;
+
+ data = inout[LSUB_QRAW + LSUB_Q -1 -i] & 0x3f;
+ if (data != 0) {
+ unsigned char base = rs_sub_rw_log[data];
+
+ Q[0] ^= rs_sub_rw_alog[(base+0*i) % ((1 << RS_SUB_RW_BITS)-1)];
+ Q[1] ^= rs_sub_rw_alog[(base+1*i) % ((1 << RS_SUB_RW_BITS)-1)];
+ }
+ }
+
+ return (Q[0] != 0 || Q[1] != 0);
+}
+int decode_LSUB_P(unsigned char inout[LSUB_RAW + LSUB_Q + LSUB_P])
+{
+ unsigned char P[LSUB_P];
+ int i;
+
+ memset(P, 0, LSUB_P);
+ for (i = LSUB_RAW + LSUB_Q + LSUB_P-1; i>=0; i--) {
+ unsigned char data;
+
+ data = inout[LSUB_RAW + LSUB_Q + LSUB_P -1 -i] & 0x3f;
+ if (data != 0) {
+ unsigned char base = rs_sub_rw_log[data];
+
+ P[0] ^= rs_sub_rw_alog[(base+0*i) % ((1 << RS_SUB_RW_BITS)-1)];
+ P[1] ^= rs_sub_rw_alog[(base+1*i) % ((1 << RS_SUB_RW_BITS)-1)];
+ P[2] ^= rs_sub_rw_alog[(base+2*i) % ((1 << RS_SUB_RW_BITS)-1)];
+ P[3] ^= rs_sub_rw_alog[(base+3*i) % ((1 << RS_SUB_RW_BITS)-1)];
+ }
+ }
+
+ return (P[0] != 0 || P[1] != 0 || P[2] != 0 || P[3] != 0);
+}
+
+/* Layer 1 CIRC en/decoder */
+#define MAX_L1_DEL1 2
+static unsigned char l1_delay_line1[MAX_L1_DEL1][L1_RAW];
+#define MAX_L1_DEL2 108
+static unsigned char l1_delay_line2[MAX_L1_DEL2][L1_RAW+L1_Q];
+#define MAX_L1_DEL3 1
+static unsigned char l1_delay_line3[MAX_L1_DEL3][L1_RAW+L1_Q+L1_P];
+static unsigned l1_del_index;
+
+int do_encode_L1(unsigned char in[L1_RAW*FRAMES_PER_SECTOR],
+ unsigned char out[(L1_RAW+L1_Q+L1_P)*FRAMES_PER_SECTOR],
+ int delay1, int delay2, int delay3, int permute)
+{
+ int i;
+
+ for (i = 0; i < FRAMES_PER_SECTOR; i++) {
+ int j;
+ unsigned char t;
+
+ if (in != out)
+ memcpy(out, in, L1_RAW);
+
+ if (delay1) {
+ /* shift through delay line 1 */
+ for (j = 0; j < L1_RAW; j++) {
+ if (((j/4) % MAX_L1_DEL1) == 0) {
+ t = l1_delay_line1[l1_del_index % (MAX_L1_DEL1)][j];
+ l1_delay_line1[l1_del_index % (MAX_L1_DEL1)][j] = out[j];
+ out[j] = t;
+ }
+ }
+ }
+
+ if (permute) {
+ /* permute */
+ t = out[2]; out[2] = out[8]; out[8] = out[10]; out[10] = out[18];
+ out[18] = out[6]; out [6] = t;
+ t = out[3]; out[3] = out[9]; out[9] = out[11]; out[11] = out[19];
+ out[19] = out[7]; out [7] = t;
+ t = out[4]; out[4] = out[16]; out[16] = out[20]; out[20] = out[14];
+ out[14] = out[12]; out [12] = t;
+ t = out[5]; out[5] = out[17]; out[17] = out[21]; out[21] = out[15];
+ out[15] = out[13]; out [13] = t;
+ }
+
+ /* build Q parity */
+ encode_L1_Q(out);
+
+ if (delay2) {
+ /* shift through delay line 2 */
+ for (j = 0; j < L1_RAW+L1_Q; j++) {
+ if (j != 0) {
+ t = l1_delay_line2[(l1_del_index) % MAX_L1_DEL2][j];
+ l1_delay_line2[(l1_del_index + j*4) % MAX_L1_DEL2][j] = out[j];
+ out[j] = t;
+ }
+ }
+ }
+
+ /* build P parity */
+ encode_L1_P(out);
+
+ if (delay3) {
+ /* shift through delay line 3 */
+ for (j = 0; j < L1_RAW+L1_Q+L1_P; j++) {
+ if (((j) & MAX_L1_DEL3) == 0) {
+ t = l1_delay_line3[0][j];
+ l1_delay_line3[0][j] = out[j];
+ out[j] = t;
+ }
+ }
+ }
+
+ /* invert Q and P parity */
+ for (j = 0; j < L1_Q; j++)
+ out[j+12] = ~out[j+12];
+ for (j = 0; j < L1_P; j++)
+ out[j+28] = ~out[j+28];
+
+ l1_del_index++;
+ out += L1_RAW+L1_Q+L1_P;
+ in += L1_RAW;
+ }
+ return 0;
+}
+
+#ifdef MAIN
+int do_decode_L1(unsigned char in[(L1_RAW+L1_Q+L1_P)*FRAMES_PER_SECTOR],
+ unsigned char out[L1_RAW*FRAMES_PER_SECTOR],
+ int delay1, int delay2, int delay3, int permute)
+{
+ int i;
+
+ for (i = 0; i < FRAMES_PER_SECTOR; i++) {
+ int j;
+ unsigned char t;
+
+ if (delay3) {
+ /* shift through delay line 3 */
+ for (j = 0; j < L1_RAW+L1_Q+L1_P; j++) {
+ if (((j) & MAX_L1_DEL3) != 0) {
+ t = l1_delay_line3[0][j];
+ l1_delay_line3[0][j] = in[j];
+ in[j] = t;
+ }
+ }
+ }
+
+ /* invert Q and P parity */
+ for (j = 0; j < L1_Q; j++)
+ in[j+12] = ~in[j+12];
+ for (j = 0; j < L1_P; j++)
+ in[j+28] = ~in[j+28];
+
+ /* build P parity */
+ decode_L1_P(in);
+
+ if (delay2) {
+ /* shift through delay line 2 */
+ for (j = 0; j < L1_RAW+L1_Q; j++) {
+ if (j != L1_RAW+L1_Q-1) {
+ t = l1_delay_line2[(l1_del_index) % MAX_L1_DEL2][j];
+ l1_delay_line2[(l1_del_index + (MAX_L1_DEL2 - j*4)) % MAX_L1_DEL2][j] = in[j];
+ in[j] = t;
+ }
+ }
+ }
+
+ /* build Q parity */
+ decode_L1_Q(in);
+
+ if (permute) {
+ /* permute */
+ t = in[2]; in[2] = in[6]; in[6] = in[18]; in[18] = in[10];
+ in[10] = in[8]; in [8] = t;
+ t = in[3]; in[3] = in[7]; in[7] = in[19]; in[19] = in[11];
+ in[11] = in[9]; in [9] = t;
+ t = in[4]; in[4] = in[12]; in[12] = in[14]; in[14] = in[20];
+ in[20] = in[16]; in [16] = t;
+ t = in[5]; in[5] = in[13]; in[13] = in[15]; in[15] = in[21];
+ in[21] = in[17]; in [17] = t;
+ }
+
+ if (delay1) {
+ /* shift through delay line 1 */
+ for (j = 0; j < L1_RAW; j++) {
+ if (((j/4) % MAX_L1_DEL1) != 0) {
+ t = l1_delay_line1[l1_del_index % (MAX_L1_DEL1)][j];
+ l1_delay_line1[l1_del_index % (MAX_L1_DEL1)][j] = in[j];
+ in[j] = t;
+ }
+ }
+ }
+
+ if (in != out)
+ memcpy(out, in, (L1_RAW));
+
+ l1_del_index++;
+ in += L1_RAW+L1_Q+L1_P;
+ out += L1_RAW;
+ }
+ return 0;
+}
+
+#endif
+
+#if 0
+static unsigned char bin2bcd(unsigned p)
+{
+ return ((p/10)<<4)|(p%10);
+}
+#endif
+
+static int build_address(unsigned char inout[], int sectortype, unsigned address)
+{
+ inout[12] = minute;
+ inout[13] = second;
+ inout[14] = frame;
+ if (sectortype == MODE_0)
+ inout[15] = 0;
+ else if (sectortype == MODE_1)
+ inout[15] = 1;
+ else if (sectortype == MODE_2)
+ inout[15] = 2;
+ else if (sectortype == MODE_2_FORM_1)
+ inout[15] = 2;
+ else if (sectortype == MODE_2_FORM_2)
+ inout[15] = 2;
+ else
+ return -1;
+ return 0;
+}
+
+#include "crctable.out"
+
+unsigned long int build_edc(unsigned char inout[], int from, int upto)
+{
+ unsigned char *p = inout+from;
+ unsigned long result = 0;
+
+ for (; from <= upto; from++)
+ result = EDC_crctable[(result ^ *p++) & 0xffL] ^ (result >> 8);
+
+ return result;
+}
+
+/* Layer 2 Product code en/decoder */
+int do_encode_L2(unsigned char inout[(12 + 4 + L2_RAW+4+8+L2_Q+L2_P)], int sectortype, unsigned address)
+{
+ unsigned long int result;
+
+#define SYNCPATTERN "\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
+
+ /* supply initial sync pattern */
+ memcpy(inout, SYNCPATTERN, sizeof(SYNCPATTERN));
+
+ if (sectortype == MODE_0) {
+ memset(inout + sizeof(SYNCPATTERN), 0, 4 + L2_RAW + 12 + L2_P + L2_Q);
+ build_address(inout, sectortype, address);
+ return 0;
+ }
+
+ switch (sectortype) {
+ case MODE_1:
+ build_address(inout, sectortype, address);
+ result = build_edc(inout, 0, 16+2048-1);
+ inout[2064+0] = result >> 0L;
+ inout[2064+1] = result >> 8L;
+ inout[2064+2] = result >> 16L;
+ inout[2064+3] = result >> 24L;
+ memset(inout+2064+4, 0, 8);
+ encode_L2_P(inout+12);
+ encode_L2_Q(inout+12);
+ break;
+ case MODE_2:
+ build_address(inout, sectortype, address);
+ break;
+ case MODE_2_FORM_1:
+ result = build_edc(inout, 16, 16+8+2048-1);
+ inout[2072+0] = result >> 0L;
+ inout[2072+1] = result >> 8L;
+ inout[2072+2] = result >> 16L;
+ inout[2072+3] = result >> 24L;
+
+ /* clear header for P/Q parity calculation */
+ inout[12] = 0;
+ inout[12+1] = 0;
+ inout[12+2] = 0;
+ inout[12+3] = 0;
+ encode_L2_P(inout+12);
+ encode_L2_Q(inout+12);
+ build_address(inout, sectortype, address);
+ break;
+ case MODE_2_FORM_2:
+ build_address(inout, sectortype, address);
+ result = build_edc(inout, 16, 16+8+2324-1);
+ inout[2348+0] = result >> 0L;
+ inout[2348+1] = result >> 8L;
+ inout[2348+2] = result >> 16L;
+ inout[2348+3] = result >> 24L;
+ break;
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+#ifdef MAIN
+static int do_decode_L2(unsigned char in[(L2_RAW+L2_Q+L2_P)],
+ unsigned char out[L2_RAW])
+{
+ return 0;
+}
+#endif
+
+
+#define MAX_SUB_DEL 8
+static unsigned char sub_delay_line[MAX_SUB_DEL][LSUB_RAW+LSUB_Q+LSUB_P];
+static unsigned sub_del_index;
+
+/* R-W Subchannel en/decoder */
+int do_encode_sub(unsigned char in[LSUB_RAW*PACKETS_PER_SUBCHANNELFRAME],
+ unsigned char out[(LSUB_RAW+LSUB_Q+LSUB_P)*PACKETS_PER_SUBCHANNELFRAME],
+ int delay1, int permute)
+{
+ int i;
+
+ if (in == out) return -1;
+
+ for (i = 0; i < PACKETS_PER_SUBCHANNELFRAME; i++) {
+ int j;
+ unsigned char t;
+
+ memcpy(out, in, (LSUB_RAW));
+
+ /* build Q parity */
+ encode_LSUB_Q(out);
+
+ /* build P parity */
+ encode_LSUB_P(out);
+
+ if (permute) {
+ /* permute */
+ t = out[1]; out[1] = out[18]; out[18] = t;
+ t = out[2]; out[2] = out[ 5]; out[ 5] = t;
+ t = out[3]; out[3] = out[23]; out[23] = t;
+ }
+
+ if (delay1) {
+ /* shift through delay_line */
+ for (j = 0; j < LSUB_RAW+LSUB_Q+LSUB_P; j++) {
+ if ((j % MAX_SUB_DEL) != 0) {
+ t = sub_delay_line[(sub_del_index) % MAX_SUB_DEL][j];
+ sub_delay_line[(sub_del_index + j) % MAX_SUB_DEL][j] = out[j];
+ out[j] = t;
+ }
+ }
+ }
+ sub_del_index++;
+ out += LSUB_RAW+LSUB_Q+LSUB_P;
+ in += LSUB_RAW;
+ }
+ return 0;
+}
+
+int
+do_decode_sub(
+ unsigned char in[(LSUB_RAW+LSUB_Q+LSUB_P)*PACKETS_PER_SUBCHANNELFRAME],
+ unsigned char out[LSUB_RAW*PACKETS_PER_SUBCHANNELFRAME],
+ int delay1, int permute)
+{
+ int i;
+
+ if (in == out) return -1;
+
+ for (i = 0; i < PACKETS_PER_SUBCHANNELFRAME; i++) {
+ int j;
+ unsigned char t;
+
+ if (delay1) {
+ /* shift through delay_line */
+ for (j = 0; j < LSUB_RAW+LSUB_Q+LSUB_P; j++) {
+ if ((j % MAX_SUB_DEL) != MAX_SUB_DEL-1) {
+ t = sub_delay_line[(sub_del_index) % MAX_SUB_DEL][j];
+ sub_delay_line[(sub_del_index + (MAX_SUB_DEL - j)) % MAX_SUB_DEL][j] = in[j];
+ in[j] = t;
+ }
+ }
+ }
+
+ if (permute) {
+ /* permute */
+ t = in[1]; in[1] = in[18]; in[18] = t;
+ t = in[2]; in[2] = in[ 5]; in[ 5] = t;
+ t = in[3]; in[3] = in[23]; in[23] = t;
+ }
+
+ /* build P parity */
+ decode_LSUB_P(in);
+
+ /* build Q parity */
+ decode_LSUB_Q(in);
+
+ memcpy(out, in, LSUB_QRAW);
+ memcpy(out+LSUB_QRAW, in+LSUB_QRAW+LSUB_Q, LSUB_RAW-LSUB_QRAW);
+
+ sub_del_index++;
+ in += LSUB_RAW+LSUB_Q+LSUB_P;
+ out += LSUB_RAW;
+ }
+ return 0;
+}
+
+static int sectortype = MODE_0;
+int get_sector_type(void)
+{
+ return sectortype;
+}
+
+int set_sector_type(int st)
+{
+ switch(st) {
+ case MODE_0:
+ case MODE_1:
+ case MODE_2:
+ case MODE_2_FORM_1:
+ case MODE_2_FORM_2:
+ sectortype = st;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+/* ------------- --------------*/
+#ifdef MAIN
+
+#define DO_L1 1
+#define DO_L2 2
+#define DO_SUB 4
+
+static const unsigned sect_size[8][2] = {
+/* nothing */
+{0,0},
+/* Layer 1 decode/encode */
+{ (L1_RAW+L1_Q+L1_P)*FRAMES_PER_SECTOR, L1_RAW*FRAMES_PER_SECTOR},
+/* Layer 2 decode/encode */
+{ 16+L2_RAW+12+L2_Q+L2_P, L2_RAW},
+/* Layer 1 and 2 decode/encode */
+{ (L1_RAW+L1_Q+L1_P)*FRAMES_PER_SECTOR, L1_RAW*FRAMES_PER_SECTOR},
+/* Subchannel decode/encode */
+{ (LSUB_RAW+LSUB_Q+LSUB_P)*PACKETS_PER_SUBCHANNELFRAME,
+ LSUB_RAW*PACKETS_PER_SUBCHANNELFRAME},
+/* Layer 1 and subchannel decode/encode */
+{ (L1_RAW+L1_Q+L1_P)*FRAMES_PER_SECTOR +
+ (LSUB_RAW+LSUB_Q+LSUB_P)*PACKETS_PER_SUBCHANNELFRAME,
+ LSUB_RAW*PACKETS_PER_SUBCHANNELFRAME +
+ L1_RAW*FRAMES_PER_SECTOR},
+/* Layer 2 and subchannel decode/encode */
+{ L2_RAW+L2_Q+L2_P+
+ (LSUB_RAW+LSUB_Q+LSUB_P)*PACKETS_PER_SUBCHANNELFRAME,
+ LSUB_RAW*PACKETS_PER_SUBCHANNELFRAME +
+ L2_RAW},
+/* Layer 1, 2 and subchannel decode/encode */
+{ (L1_RAW+L1_Q+L1_P)*FRAMES_PER_SECTOR +
+ (LSUB_RAW+LSUB_Q+LSUB_P)*PACKETS_PER_SUBCHANNELFRAME,
+ LSUB_RAW*PACKETS_PER_SUBCHANNELFRAME +
+ L1_RAW*FRAMES_PER_SECTOR},
+};
+
+int main(int argc, char **argv)
+{
+ int encode = 1;
+ int mask = DO_L2;
+ FILE * infp;
+ FILE * outfp;
+ unsigned address = 0;
+ unsigned char *l1_inbuf;
+ unsigned char *l1_outbuf;
+ unsigned char *l2_inbuf;
+ unsigned char *l2_outbuf;
+ unsigned char *sub_inbuf;
+ unsigned char *sub_outbuf;
+ unsigned char *last_outbuf;
+ unsigned char inbuf[(LSUB_RAW+LSUB_Q+LSUB_P)*PACKETS_PER_SUBCHANNELFRAME +
+ (L1_RAW+L1_Q+L1_P)*FRAMES_PER_SECTOR];
+ unsigned char outbuf[(LSUB_RAW+LSUB_Q+LSUB_P)*PACKETS_PER_SUBCHANNELFRAME +
+ (L1_RAW+L1_Q+L1_P)*FRAMES_PER_SECTOR];
+ unsigned load_offset;
+
+ l1_inbuf = l2_inbuf = sub_inbuf = inbuf;
+ l1_outbuf = l2_outbuf = sub_outbuf = last_outbuf = outbuf;
+
+ infp = fopen("sectors_in", "rb");
+ outfp = fopen("sectors_out", "wb");
+
+ sectortype= MODE_2_FORM_1;
+ address = 0 + 75*2;
+
+ switch (sectortype) {
+ case MODE_1:
+ case MODE_2:
+ load_offset = 16;
+ break;
+ case MODE_2_FORM_1:
+ case MODE_2_FORM_2:
+ load_offset = 24;
+ break;
+ default:
+ load_offset = 0;
+ }
+ while(1) {
+
+ if (1 != fread(inbuf+load_offset,
+ sect_size[mask][encode], 1, infp)) { perror(""); break; }
+ if (encode == 1) {
+ if (mask & DO_L2) {
+ switch (sectortype) {
+ case MODE_0:
+ break;
+ case MODE_1:
+ break;
+ case MODE_2:
+ if (1 !=
+ fread(inbuf+load_offset+
+ sect_size[mask][encode],
+ 2336 - sect_size[mask][encode],
+ 1, infp)) { perror(""); break; }
+ break;
+ case MODE_2_FORM_1:
+ break;
+ case MODE_2_FORM_2:
+ if (1 !=
+ fread(inbuf+load_offset+
+ sect_size[mask][encode],
+ 2324 - sect_size[mask][encode],
+ 1, infp)) { perror(""); break; }
+ break;
+ default:
+ if (1 !=
+ fread(inbuf+load_offset+
+ sect_size[mask][encode],
+ 2448 - sect_size[mask][encode],
+ 1, infp)) { perror(""); break; }
+ memset(inbuf,0,16);
+ /*memset(inbuf+16+2048,0,12+272);*/
+ break;
+ }
+ do_encode_L2(l2_inbuf, MODE_1, address);
+ if (0) scramble_L2(l2_inbuf);
+ last_outbuf = l1_inbuf = l2_inbuf;
+ l1_outbuf = l2_inbuf;
+ sub_inbuf = l2_inbuf + L2_RAW;
+ sub_outbuf = l2_outbuf + 12 + 4+ L2_RAW+4+ 8+ L2_Q+L2_P;
+ }
+ if (mask & DO_L1) {
+ do_encode_L1(l1_inbuf, l1_outbuf,1,1,1,1);
+ last_outbuf = l1_outbuf;
+ sub_inbuf = l1_inbuf + L1_RAW*FRAMES_PER_SECTOR;
+ sub_outbuf = l1_outbuf + (L1_RAW+L1_Q+L1_P)*FRAMES_PER_SECTOR;
+ }
+ if (mask & DO_SUB) {
+ do_encode_sub(sub_inbuf, sub_outbuf, 0, 0);
+ }
+ } else {
+ if (mask & DO_L1) {
+ do_decode_L1(l1_inbuf, l1_outbuf,1,1,1,1);
+ last_outbuf = l2_inbuf = l1_outbuf;
+ l2_outbuf = l1_inbuf;
+ sub_inbuf = l1_inbuf + (L1_RAW+L1_Q+L1_P)*FRAMES_PER_SECTOR;
+ sub_outbuf = l1_outbuf + L1_RAW*FRAMES_PER_SECTOR;
+ }
+ if (mask & DO_L2) {
+ do_decode_L2(l2_inbuf, l2_outbuf);
+ last_outbuf = l2_outbuf;
+ sub_inbuf = l2_inbuf + L2_RAW+L2_Q+L2_P;
+ sub_outbuf = l2_outbuf + L2_RAW;
+ }
+ if (mask & DO_SUB) {
+ do_decode_sub(sub_inbuf, sub_outbuf, 1, 1);
+ }
+ }
+ if (1 != fwrite(last_outbuf, sect_size[mask][1 - encode], 1, outfp)) {
+ perror("");
+ break;
+ }
+ address++;
+ }
+#if 0
+ /* flush the data from the delay lines with zeroed sectors, if necessary */
+#endif
+ return 0;
+}
+#endif
diff --git a/yazedc.h b/yazedc.h
new file mode 100644
index 0000000..b990d3e
--- /dev/null
+++ b/yazedc.h
@@ -0,0 +1,142 @@
+/*
+ * PSX-Tools Bundle Pack
+ * Copyright (C) 1998 Heiko Eissfeldt
+ * portions used& Chris Smith
+ * First modified by Yazoo, then by
+ * Nicolas "Pixel" Noble
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __YAZEDC_H__
+
+#define RS_L12_BITS 8
+
+/* audio sector definitions for CIRC */
+#define FRAMES_PER_SECTOR 98
+/* user data bytes per frame */
+#define L1_RAW 24
+/* parity bytes with 8 bit */
+#define L1_Q 4
+#define L1_P 4
+
+/* audio sector Cross Interleaved Reed-Solomon Code (CIRC) encoder (layer 1) */
+/* adds P- and Q- parity information to audio (f2) frames. Also
+ optionally handles the various delays and permutations. The output with all
+ stages enabled can be fed into the Eight-Fourteen-Modulator.
+ On input: 2352 bytes of audio data is given.
+ On output: 3136 bytes of CIRC enriched audio data are returned.
+ */
+int do_encode_L1(unsigned char in[L1_RAW*FRAMES_PER_SECTOR],
+ unsigned char out[(L1_RAW+L1_Q+L1_P)*FRAMES_PER_SECTOR],
+ int delay1, int delay2, int delay3, int scramble);
+
+/* data sector definitions for RSPC */
+/* user data bytes per frame */
+#define L2_RAW (1024*2)
+/* parity bytes for 16 bit units */
+#define L2_Q (26*2*2)
+#define L2_P (43*2*2)
+
+/* known sector types */
+#define MODE_0 0
+#define MODE_1 1
+#define MODE_2 2
+#define MODE_2_FORM_1 3
+#define MODE_2_FORM_2 4
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* set one of the MODE_* constants for subsequent data sector formatting */
+int set_sector_type(int st);
+/* get the current sector type setting for data sector formatting */
+int get_sector_type(void);
+
+/* data sector layer 2 Reed-Solomon Product Code encoder */
+/* encode the given data portion depending on sector type (see
+ get/set_sector_type() functions). Use the given address for the header.
+ The returned data is __unscrambled__ and not in F2-frame format (for that
+ see function scramble_L2()).
+ Supported sector types:
+ MODE_0: a 12-byte sync field, a header and 2336 zeros are returned.
+ MODE_1: the user data portion (2048 bytes) has to be given
+ at offset 16 in the inout array.
+ Sync-, header-, edc-, spare-, p- and q- fields will be added.
+ MODE_2: the user data portion (2336 bytes) has to be given
+ at offset 16 in the inout array.
+ Sync- and header- fields will be added.
+ MODE_2_FORM_1: the user data portion (8 bytes subheader followed
+ by 2048 bytes data) has to be given at offset 16
+ in the inout array.
+ Sync-, header-, edc-, p- and q- fields will be added.
+ MODE_2_FORM_2: the user data portion (8 bytes subheader followed
+ by 2324 bytes data) has to be given at offset 16
+ in the inout array.
+ Sync-, header- and edc- fields will be added.
+*/
+int do_encode_L2(unsigned char *inout, int sectortype, unsigned address);
+int decode_L2_Q(unsigned char inout[4 + L2_RAW + 12 + L2_Q]);
+int decode_L2_P(unsigned char inout[4 + L2_RAW + 12 + L2_Q + L2_P]);
+unsigned long int build_edc(unsigned char inout[], int from, int upto);
+
+/* generates f2 frames from otherwise fully formatted sectors (generated by
+ do_encode_L2()). */
+int scramble_L2(unsigned char *inout);
+
+#ifdef __cplusplus
+}
+#endif
+
+/* r-w sub channel definitions */
+#define RS_SUB_RW_BITS 6
+
+#define PACKETS_PER_SUBCHANNELFRAME 4
+#define LSUB_RAW 18
+#define LSUB_QRAW 2
+/* 6 bit */
+#define LSUB_Q 2
+#define LSUB_P 4
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* R-W subchannel encoder */
+/* On input: 72 bytes packed user data, four frames with each 18 bytes.
+ On output: per frame: 2 bytes user data, 2 bytes Q parity,
+ 16 bytes user data, 4 bytes P parity.
+ Options:
+ delay1: use low level delay line
+ scramble: perform low level permutations
+ */
+int do_encode_sub(unsigned char in[LSUB_RAW*PACKETS_PER_SUBCHANNELFRAME],
+ unsigned char out[(LSUB_RAW+LSUB_Q+LSUB_P)*PACKETS_PER_SUBCHANNELFRAME],
+ int delay1, int scramble);
+int do_decode_sub(unsigned char in[(LSUB_RAW+LSUB_Q+LSUB_P)*PACKETS_PER_SUBCHANNELFRAME],
+ unsigned char out[LSUB_RAW*PACKETS_PER_SUBCHANNELFRAME],
+ int delay1, int scramble);
+
+int decode_LSUB_Q(unsigned char inout[LSUB_QRAW + LSUB_Q]);
+int decode_LSUB_P(unsigned char inout[LSUB_RAW + LSUB_Q + LSUB_P]);
+
+#ifdef __cplusplus
+}
+#endif
+
+extern unsigned char minute, second, frame;
+
+#endif