From 24fb33726eca4e8c5a88797adc9c17f4d541f543 Mon Sep 17 00:00:00 2001 From: Pixel Date: Sat, 4 May 2002 17:53:08 +0000 Subject: Initial revision --- AUTHOR | 4 + COPYING | 340 ++++++++++++++ FAQ | 0 FAQ.cd | 203 +++++++++ FAQ.lz77 | 207 +++++++++ Makefile | 23 + VP/main_dump.cpp | 290 ++++++++++++ Xenogears/Decrypt.cpp | 507 +++++++++++++++++++++ Xenogears/Makefile | 23 + Xenogears/Translate.cpp | 256 +++++++++++ Xenogears/XenoCD1.map | 52 +++ Xenogears/XenoCD2.map | 52 +++ Xenogears/archive.cpp | 37 ++ Xenogears/build-sector-2.cpp | 14 + Xenogears/build-sector.cpp | 14 + Xenogears/compil-2.lex | 254 +++++++++++ Xenogears/compil.lex | 383 ++++++++++++++++ Xenogears/main_dump.cpp | 291 ++++++++++++ Xenogears/map2sqr | 34 ++ Xenogears/reinsert.cpp | 305 +++++++++++++ Xenogears/script-comp.cpp | 96 ++++ Xenogears/script-dec.cpp | 69 +++ Xenogears/test-dlz77.cpp | 7 + Xenogears/test-lz77.cpp | 7 + cd-tool | Bin 0 -> 144519 bytes cd-tool.cpp | 273 ++++++++++++ cdutils.cpp | 634 ++++++++++++++++++++++++++ cdutils.h | 83 ++++ crctable.out | 91 ++++ crctables | 142 ++++++ fileutils.cpp | 50 +++ fileutils.h | 40 ++ generic.cpp | 56 +++ generic.h | 37 ++ info-cd.cpp | 40 ++ lz77 | Bin 0 -> 232764 bytes lz77.cpp | 757 +++++++++++++++++++++++++++++++ lz77.h | 60 +++ yazedc | Bin 0 -> 68824 bytes yazedc.cpp | 1017 ++++++++++++++++++++++++++++++++++++++++++ yazedc.h | 142 ++++++ 41 files changed, 6890 insertions(+) create mode 100644 AUTHOR create mode 100644 COPYING create mode 100644 FAQ create mode 100644 FAQ.cd create mode 100644 FAQ.lz77 create mode 100755 Makefile create mode 100644 VP/main_dump.cpp create mode 100644 Xenogears/Decrypt.cpp create mode 100755 Xenogears/Makefile create mode 100644 Xenogears/Translate.cpp create mode 100644 Xenogears/XenoCD1.map create mode 100644 Xenogears/XenoCD2.map create mode 100644 Xenogears/archive.cpp create mode 100644 Xenogears/build-sector-2.cpp create mode 100644 Xenogears/build-sector.cpp create mode 100644 Xenogears/compil-2.lex create mode 100644 Xenogears/compil.lex create mode 100644 Xenogears/main_dump.cpp create mode 100755 Xenogears/map2sqr create mode 100644 Xenogears/reinsert.cpp create mode 100644 Xenogears/script-comp.cpp create mode 100644 Xenogears/script-dec.cpp create mode 100644 Xenogears/test-dlz77.cpp create mode 100644 Xenogears/test-lz77.cpp create mode 100755 cd-tool create mode 100644 cd-tool.cpp create mode 100644 cdutils.cpp create mode 100644 cdutils.h create mode 100644 crctable.out create mode 100644 crctables create mode 100644 fileutils.cpp create mode 100644 fileutils.h create mode 100644 generic.cpp create mode 100644 generic.h create mode 100644 info-cd.cpp create mode 100755 lz77 create mode 100644 lz77.cpp create mode 100644 lz77.h create mode 100755 yazedc create mode 100644 yazedc.cpp create mode 100644 yazedc.h 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. + + + Copyright (C) + + 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. + + , 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 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, find. + + then you will decompress it by: + + One Ring to rule them all, One Ring to find them. + + because when you hit the , it tells you to copy 12 bytes from + 27 bytes backward, and when you hit the , 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 + + This is obvious hu? Now, with the overlap trick: + + 123 + + 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 +#include +#include +#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 \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 +#include + +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, "\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) // "" + { + break; + } else if (val == 0x01) // "\n" + { + fprintf(f_cible, "\n"); + } else if (val == 0x02) // "" + { + fprintf(f_cible, "\n"); + } else if (val == 0x03) // "" + { + fprintf(f_cible, ""); + } else if (val == 0x0F) // " + { + fread((unsigned char *) &temp1, 1, 1, f_source); + fread((unsigned char *) &temp2, 1, 1, f_source); + if (temp1 == 0) { + fprintf(f_cible, "", temp2); + } else if (temp1 == 5) { + switch (temp2) { + case 0: + fprintf(f_cible, ""); + break; + case 1: + fprintf(f_cible, ""); + break; + case 2: + fprintf(f_cible, ""); + break; + case 3: + fprintf(f_cible, ""); + break; + case 4: + fprintf(f_cible, ""); + break; + case 5: + fprintf(f_cible, ""); + break; + case 6: + fprintf(f_cible, ""); + break; + case 7: + fprintf(f_cible, ""); + break; + case 8: + fprintf(f_cible, ""); + break; + case 9: + fprintf(f_cible, ""); + break; + case 10: + fprintf(f_cible, ""); + break; + case 11: + fprintf(f_cible, ""); + break; + case 12: + fprintf(f_cible, ""); + break; + case 13: + fprintf(f_cible, ""); + break; + case 14: + fprintf(f_cible, ""); + break; + case 15: + fprintf(f_cible, ""); + break; + case 16: + fprintf(f_cible, ""); + break; + case 17: + fprintf(f_cible, ""); + break; + case 18: + fprintf(f_cible, ""); + break; + case 19: + fprintf(f_cible, ""); + break; + case 20: + fprintf(f_cible, ""); + break; + case 21: + fprintf(f_cible, ""); + break; + case 22: + fprintf(f_cible, ""); + break; + case 23: + fprintf(f_cible, ""); + break; + case 24: + fprintf(f_cible, ""); + break; + case 25: + fprintf(f_cible, ""); + break; + case 26: + fprintf(f_cible, ""); + break; + case 27: + fprintf(f_cible, ""); + break; + case 28: + fprintf(f_cible, ""); + break; + case 128: + fprintf(f_cible, ""); + break; + case 129: + fprintf(f_cible, ""); + break; + case 130: + fprintf(f_cible, ""); + break; + default: + fprintf(f_cible, "", temp2); + } + } else { + fprintf(f_cible, "", 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) // "" + { + fprintf(f_cible, ""); + } else if (val == 0x6F) // "" + { + fprintf(f_cible, ""); + } else if (val == 0x70) // "" + { + fprintf(f_cible, ""); + } else if (val == 0x71) // "<*>" + { + fprintf(f_cible, "<*>"); + } else if (val == 0x72) // "" + { + fprintf(f_cible, ""); + } else if (val == 0x73) // "" + { + fprintf(f_cible, ""); + } else if (val == 0x74) // "" + { + fprintf(f_cible, ""); + } else if (val == 0x75) // "" + { + fprintf(f_cible, ""); + } 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) // "" + { + fprintf(f_cible, ""); + } 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) // " + { + fread((unsigned char *) &temp1, 1, 1, f_source); + fprintf(f_cible, "", temp1); + } else if (val == 0xFF) // " + { + fread((unsigned char *) &temp1, 1, 1, f_source); + fprintf(f_cible, "", temp1); + } else { + fprintf(f_cible, "", val); + } + + position = ftell(f_source); + } + fprintf(f_cible, "\n\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, "\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 +#include + +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) // "" + { +// break; + fprintf(f_cible, "\n"); + } else if (val == 0x01) // "\n" + { + fprintf(f_cible, "\n"); + } else if (val == 0x02) // "" + { + fprintf(f_cible, "\n"); + } else if (val == 0x03) // "" + { + fprintf(f_cible, ""); + } else if (val == 0x0F) // " + { + fread((unsigned char *) &temp1, 1, 1, f_source); + fread((unsigned char *) &temp2, 1, 1, f_source); + if (temp1 == 0) { + fprintf(f_cible, "", temp2); + } else if (temp1 == 5) { + fprintf(f_cible, "", temp2); + } else { + fprintf(f_cible, "", 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) // "" + { + fprintf(f_cible, ""); + } else if (val == 0x6F) // "" + { + fprintf(f_cible, ""); + } else if (val == 0x70) // "" + { + fprintf(f_cible, ""); + } else if (val == 0x71) // "<*>" + { + fprintf(f_cible, "<*>"); + } else if (val == 0x72) // "" + { + fprintf(f_cible, ""); + } else if (val == 0x73) // "" + { + fprintf(f_cible, ""); + } else if (val == 0x74) // "" + { + fprintf(f_cible, ""); + } else if (val == 0x75) // "" + { + fprintf(f_cible, ""); + } 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) // "" + { + fprintf(f_cible, ""); + } 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) // " + { + fread((unsigned char *) &temp1, 1, 1, f_source); + fprintf(f_cible, "", temp1); + } else if (val == 0xFF) // " + { + fread((unsigned char *) &temp1, 1, 1, f_source); + fprintf(f_cible, "", temp1); + } else { + fprintf(f_cible, "", 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 +#include +#include +#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 +#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 +#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); + +%% + +""\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); + } + +.* { + fprintf(stderr, "Invalid file, must begin with \n"); + errstate = 1; + num_lines = 2; + num_blocks = 9999; + } + +"= num_blocks) { + fprintf(stderr, "Error: too much blocks at line %i\n", num_lines); + errstate = 1; + } + block_lines = atoi(yytext + 18); + BEGIN(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); + } + +.* { + fprintf(stderr, "Error: invalid arguments to command Text_block at line %i: '%s'\n", num_lines, yytext); + errstate = 1; + BEGIN(O); + } + +\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); + } + +"\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); + } + +"\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); + } + +"" { + cur_num_lines = 1; + } + +"" { + int d = atoi(yytext + 7); + if (d > 255) { + fprintf(stderr, "Error: delay too important: %i\n", d); + errstate = 1; + } + } + +"" { + 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; + } + } + +"" { + BEGIN(Op); + } + +[[:digit:]]+\ +[[:digit:]]+">" { + int o1, o2; + o1 = atoi(yytext); + o2 = atoi(yytext + (o1 < 10 ? 2 : o1 < 100 ? 3 : 4)); + BEGIN(I); + } + +[^<]*">" { + yytext[strlen(yytext - 1)] = 0; + fprintf(stderr, "Error: invalid OpCode '%s'\n", yytext); + errstate = 1; + BEGIN(I); + } + +"<"[[:digit:]]">" unput(*(yytext + 1)); +"<".">" unput(*(yytext + 1)); +"<..>" unput('.'); unput('.'); +"<...>" unput('.'); unput('.'); unput('.'); + +"" { + 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); + } + } + +"" { + 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); + } + } + +"" { + 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); + } + } + +"" unput('e'); unput('o'); +"" unput('e'); unput('a'); + +"\n" { + 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); + } + +"<"[^\>\n]*">" { + yytext[strlen(yytext) - 1] = 0; + fprintf(stderr, "Error: Invalid command at line %i: '%s'\n", num_lines, yytext + 1); + errstate = 1; + } + +\n num_lines++; +. /* Eat up comments */ + +. { + 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 [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 + /* 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 *); + +%% + +""\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); + } + +.* { + fprintf(stderr, "Invalid file, must begin with \n"); + errstate = 1; + num_lines = 2; + num_blocks = 9999; + } + +"= num_blocks) { + fprintf(stderr, "Error: too much blocks at line %i\n", num_lines); + errstate = 1; + } + block_lines = atoi(yytext + 18); + BEGIN(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); + } + +.* { + fprintf(stderr, "Error: invalid arguments to command Text_block at line %i: '%s'\n", num_lines, yytext); + errstate = 1; + BEGIN(O); + } + +"\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); + } + +"\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); + } + +"\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); + } + +"" { + cur_num_lines = 1; + putc(3, yyout); + } + +"" { + 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); + } + } + +"" { + 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; + } + } + +"" { + BEGIN(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); + } + +[^<]*">" { + yytext[strlen(yytext - 1)] = 0; + fprintf(stderr, "Error: invalid OpCode '%s'\n", yytext); + errstate = 1; + BEGIN(I); + } + +" " yputc(0x10, 2); +"+" yputc(0x11, 2); +"," yputc(0x12, 2); +"-" yputc(0x13, 2); +"." yputc(0x14, 2); +"/" yputc(0x15, 2); +[[:digit:]] yputc(*yytext - 0x1a, 2); +[[:upper:]] yputc(*yytext - 0x21, 2); +"[" yputc(0x3a, 2); +"]" yputc(0x3b, 2); +"=" yputc(0x3c, 2); +[[:lower:]] yputc(*yytext - 0x24, 2); +"!" yputc(0x57, 2); +"\"" yputc(0x58, 2); +"#" yputc(0x59, 2); +"%" yputc(0x5a, 2); +"&" yputc(0x5b, 2); +"'" yputc(0x5c, 2); +"(" yputc(0x5d, 2); +")" yputc(0x5e, 2); +":" yputc(0x5f, 2); +"?" yputc(0x60, 2); +"<"[[:digit:]]">" yputc(*(yytext + 1) + 0x31, 3); +"<%>" yputc(0x6b, 3); +"<&>" yputc(0x6c, 3); +"*" yputc(0x6d, 3); +"" yputc(0x6e, 3); +"" yputc(0x6f, 3); +"" yputc(0x70, 3); +"<*>" yputc(0x71, 3); +"" yputc(0x72, 3); +"" yputc(0x73, 3); +"" yputc(0x74, 3); +"" yputc(0x75, 3); +"<.>" yputc(0x76, 3); +"<:>" yputc(0x77, 3); +"" yputc(0x79, 3); +"<..>" yputc(0x7a, 3); +"<`>" yputc(0x7b, 3); +"<+>" yputc(0x7d, 3); +"<->" yputc(0x7e, 3); +"" yputc(0x7f, 3); +"<[>" yputc(0x80, 3); +"<]>" yputc(0x81, 3); +"<(>" yputc(0x84, 3); +"<)>" yputc(0x85, 3); +"<#>" yputc(0x86, 3); +"`" yputc(0x87, 3); +"°" yputc(0x88, 3); +"<=>" yputc(0x89, 3); +"" yputc(0x8a, 3); +"" yputc(0x8b, 3); +"_" yputc(0x8c, 3); +"~" yputc(0x8d, 3); +"<...>" yputc(0x8e, 3); +"<'>" yputc(0x8f, 3); + +"" { + 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); + } + } + +"" { + 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); + } + } + +"" { + 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); + } + } + +à|â|ä unput('a'); +é|è|ê|ë unput('e'); +î|ï unput('i'); +ô|ö unput('o'); +û|ü|ù unput('u'); +ç unput('c'); +"" unput('e'); unput('o'); +"" unput('e'); unput('a'); + +"" unputs(""); +"" unputs(""); +"" unputs(""); +"" unputs(""); +"" unputs(""); +"" unputs(""); +"" unputs(""); +"" unputs(""); +"" unputs(""); +"" unputs(""); +"" unputs(""); +"" unputs(""); +"" unputs(""); +"" unputs(""); +"" unputs(""); +"" unputs(""); +"" unputs(""); +"" unputs(""); +"" unputs(""); +"" unputs(""); +"" unputs(""); +"" unputs(""); +"" unputs(""); +"" unputs(""); +"" unputs(""); +"" unputs(""); +"" unputs(""); +"" unputs(""); +"" unputs(""); +"" unputs(""); +"" unputs(""); +"" unputs(""); + + +"\n" { + 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); + } + +"<"[^\>\n]*">" { + yytext[strlen(yytext) - 1] = 0; + fprintf(stderr, "Error: Invalid command at line %i: '%s'\n", num_lines, yytext + 1); + errstate = 1; + } + +\n num_lines++; +. /* Eat up comments */ + +. { + 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 [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 +#include +#include +#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 \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 +#include +#include +#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 [-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 +#include +#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 +#include +#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 +#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 +#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 Binary files /dev/null and b/cd-tool 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 +#include +#include +#include +#include +#include +#include +#include +#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 ] [-p ] [-f] [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 - show the directoy listing of \n" +" extract-file - extract the file to \n" +" extract - extract some sectors to \n" +" insert-file - insert the file to \n" +" insert - insert some sectors at \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 +#include +#include +#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 + +#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 +#include +#include +#include +#include +#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 +#include +#include +#include +#include + +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 +#include + +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 +#include +#include +#include +#include +#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 Binary files /dev/null and b/lz77 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 +#include +#include +#include +#include +#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 ] [-l ] [-S] [-v] \n" +"\n" +"-c --compress Compress to \n" +"-d --decompress Decompress to \n" +"-s --scheme= Loads the built-in scheme number \n" +"-l --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 +#include + +#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 Binary files /dev/null and b/yazedc 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 +#include +#include +#include +#include +#include + +#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 -- cgit v1.2.3