├── COPYING.DOC ├── Makefile ├── build.txt ├── cheats.c ├── cheats.h ├── common.h ├── cpu.c ├── cpu.h ├── cpu_threaded.c ├── dc ├── Makefile ├── cd │ ├── IP.BIN │ ├── gbaDC │ │ ├── DangerousXmas.bin │ │ ├── Doom (USA, Europe).cht │ │ ├── Super Mario Advance (USA, Europe).cht │ │ └── game_config.txt │ └── gba_bios.bin ├── dc.sh ├── gbapspDC.cdi ├── gdC.elf ├── sh4_emit.h └── sh4_stub.c ├── font.h ├── game_config.txt ├── gp2x ├── Makefile ├── arm_emit.h ├── arm_stub.c ├── cpuctrl.gpl.txt ├── gp2x.c └── gp2x.h ├── gui.c ├── gui.h ├── input.c ├── input.h ├── main.c ├── main.h ├── memory.c ├── memory.h ├── mips_stub.S ├── psp ├── ICON0.png ├── Makefile ├── PIC1.png ├── mips_emit.h └── mips_stub.S ├── readme.txt ├── sound.c ├── sound.h ├── video.c ├── video.h ├── x86 ├── Makefile ├── x86_emit.h └── x86_stub.S ├── zip.c └── zip.h /COPYING.DOC: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc. 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License 307 | along with this program; if not, write to the Free Software 308 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 309 | 310 | 311 | Also add information on how to contact you by electronic and paper mail. 312 | 313 | If the program is interactive, make it output a short notice like this 314 | when it starts in an interactive mode: 315 | 316 | Gnomovision version 69, Copyright (C) year name of author 317 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 318 | This is free software, and you are welcome to redistribute it 319 | under certain conditions; type `show c' for details. 320 | 321 | The hypothetical commands `show w' and `show c' should show the appropriate 322 | parts of the General Public License. Of course, the commands you use may 323 | be called something other than `show w' and `show c'; they could even be 324 | mouse-clicks or menu items--whatever suits your program. 325 | 326 | You should also get your employer (if you work as a programmer) or your 327 | school, if any, to sign a "copyright disclaimer" for the program, if 328 | necessary. Here is a sample; alter the names: 329 | 330 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 331 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 332 | 333 | , 1 April 1989 334 | Ty Coon, President of Vice 335 | 336 | This General Public License does not permit incorporating your program into 337 | proprietary programs. If your program is a subroutine library, you may 338 | consider it more useful to permit linking proprietary applications with the 339 | library. If this is what you want to do, use the GNU Lesser General 340 | Public License instead of this License. 341 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # gpSP makefile 2 | # Gilead Kutnick - Exophase 3 | 4 | # Global definitions 5 | 6 | CC = gcc 7 | STRIP = strip 8 | AS = as 9 | 10 | PREFIX = /usr 11 | OBJS = main.o cpu.o memory.o video.o input.o \ 12 | sound.o cpu_threaded.o gui.o x86_stub.o 13 | BIN = gpsp.exe 14 | 15 | # Platform specific definitions 16 | 17 | CFLAGS += 18 | INCLUDES = -I${PREFIX}/include `sdl-config --cflags` 19 | LIBS = -L${PREFIX}/lib `sdl-config --libs` -mconsole 20 | 21 | # Compilation: 22 | 23 | .SUFFIXES: .c .S 24 | 25 | %.o: %.c 26 | ${CC} ${CFLAGS} ${INCLUDES} -c -o $@ $< 27 | 28 | %.o: %.S 29 | ${AS} -o $@ $< 30 | 31 | all: ${OBJS} 32 | ${CC} ${OBJS} ${LIBS} -o ${BIN} 33 | ${STRIP} ${BIN} 34 | 35 | clean: 36 | rm -f *.o ${BIN} 37 | 38 | -------------------------------------------------------------------------------- /build.txt: -------------------------------------------------------------------------------- 1 | How to build gpSP for PSP: 2 | 3 | The makefile is in the psp directory, simply go there and type make. 4 | make kxploit will build for 1.5 firmware. Be sure to include 5 | game_config.txt and gpsp.cfg in the same directory as EBOOT.PBP, as 6 | well as gba_bios.bin (not included). 7 | 8 | Dependencies as of v0.6: 9 | 10 | SDL 11 | zlib 12 | -------------------------------------------------------------------------------- /cheats.c: -------------------------------------------------------------------------------- 1 | /* gameplaySP 2 | * 3 | * Copyright (C) 2006 Exophase 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License as 7 | * published by the Free Software Foundation; either version 2 of 8 | * the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #include "common.h" 21 | 22 | cheat_type cheats[MAX_CHEATS]; 23 | u32 num_cheats; 24 | 25 | void decrypt_gsa_code(u32 *address_ptr, u32 *value_ptr, cheat_variant_enum 26 | cheat_variant) 27 | { 28 | u32 i, i2, code_position; 29 | u32 address = *address_ptr; 30 | u32 value = *value_ptr; 31 | u32 r = 0xc6ef3720; 32 | 33 | u32 seeds_v1[4] = 34 | { 35 | 0x09f4fbbd, 0x9681884a, 0x352027e9, 0xf3dee5a7 36 | }; 37 | u32 seeds_v3[4] = 38 | { 39 | 0x7aa9648f, 0x7fae6994, 0xc0efaad5, 0x42712c57 40 | }; 41 | u32 *seeds; 42 | 43 | if(cheat_variant == CHEAT_TYPE_GAMESHARK_V1) 44 | seeds = seeds_v1; 45 | else 46 | seeds = seeds_v3; 47 | 48 | for(i = 0; i < 32; i++) 49 | { 50 | value -= ((address << 4) + seeds[2]) ^ (address + r) ^ 51 | ((address >> 5) + seeds[3]); 52 | address -= ((value << 4) + seeds[0]) ^ (value + r) ^ 53 | ((value >> 5) + seeds[1]); 54 | r -= 0x9e3779b9; 55 | } 56 | 57 | *address_ptr = address; 58 | *value_ptr = value; 59 | } 60 | 61 | void add_cheats(u8 *cheats_filename) 62 | { 63 | FILE *cheats_file; 64 | u8 current_line[256]; 65 | u8 *name_ptr; 66 | u32 *cheat_code_ptr; 67 | u32 address, value; 68 | u32 num_cheat_lines; 69 | u32 cheat_name_length; 70 | cheat_variant_enum current_cheat_variant; 71 | 72 | num_cheats = 0; 73 | #ifdef _arch_dreamcast 74 | // add /cd/gbaDC/ to the cheats_filename path 75 | u8 cheats_filename2[512]; 76 | sprintf(cheats_filename2, "/cd/gbaDC/%s", cheats_filename); 77 | cheats_file = fopen(cheats_filename2, "rb"); 78 | #else 79 | cheats_file = fopen(cheats_filename, "rb"); 80 | #endif 81 | if(cheats_file) 82 | { 83 | while(fgets(current_line, 256, cheats_file)) 84 | { 85 | // Get the header line first 86 | name_ptr = strchr(current_line, ' '); 87 | if(name_ptr) 88 | { 89 | *name_ptr = 0; 90 | name_ptr++; 91 | } 92 | 93 | if(!strcasecmp(current_line, "gameshark_v1") || 94 | !strcasecmp(current_line, "gameshark_v2") || 95 | !strcasecmp(current_line, "PAR_v1") || 96 | !strcasecmp(current_line, "PAR_v2")) 97 | { 98 | current_cheat_variant = CHEAT_TYPE_GAMESHARK_V1; 99 | } 100 | else 101 | 102 | if(!strcasecmp(current_line, "gameshark_v3") || 103 | !strcasecmp(current_line, "PAR_v3")) 104 | { 105 | current_cheat_variant = CHEAT_TYPE_GAMESHARK_V3; 106 | } 107 | else 108 | { 109 | current_cheat_variant = CHEAT_TYPE_INVALID; 110 | } 111 | 112 | if(current_cheat_variant != CHEAT_TYPE_INVALID) 113 | { 114 | strncpy(cheats[num_cheats].cheat_name, name_ptr, CHEAT_NAME_LENGTH - 1); 115 | cheats[num_cheats].cheat_name[CHEAT_NAME_LENGTH - 1] = 0; 116 | cheat_name_length = strlen(cheats[num_cheats].cheat_name); 117 | if (cheat_name_length > 0 && 118 | ((cheats[num_cheats].cheat_name[cheat_name_length - 1] == '\n') || 119 | (cheats[num_cheats].cheat_name[cheat_name_length - 1] == '\r'))) 120 | { 121 | cheats[num_cheats].cheat_name[cheat_name_length - 1] = 0; 122 | cheat_name_length--; 123 | } 124 | 125 | 126 | if(cheat_name_length && 127 | cheats[num_cheats].cheat_name[cheat_name_length - 1] == '\r') 128 | { 129 | cheats[num_cheats].cheat_name[cheat_name_length - 1] = 0; 130 | } 131 | 132 | cheats[num_cheats].cheat_variant = current_cheat_variant; 133 | cheat_code_ptr = cheats[num_cheats].cheat_codes; 134 | num_cheat_lines = 0; 135 | 136 | while(fgets(current_line, 256, cheats_file)) 137 | { 138 | if(strlen(current_line) < 3) 139 | break; 140 | 141 | sscanf(current_line, "%08x %08x", &address, &value); 142 | 143 | decrypt_gsa_code(&address, &value, current_cheat_variant); 144 | 145 | cheat_code_ptr[0] = address; 146 | cheat_code_ptr[1] = value; 147 | 148 | cheat_code_ptr += 2; 149 | num_cheat_lines++; 150 | } 151 | 152 | cheats[num_cheats].num_cheat_lines = num_cheat_lines; 153 | 154 | num_cheats++; 155 | } 156 | } 157 | 158 | fclose(cheats_file); 159 | } 160 | } 161 | 162 | void process_cheat_gs1(cheat_type *cheat) 163 | { 164 | u32 cheat_opcode; 165 | u32 *code_ptr = cheat->cheat_codes; 166 | u32 address, value; 167 | u32 i; 168 | 169 | for(i = 0; i < cheat->num_cheat_lines; i++) 170 | { 171 | address = code_ptr[0]; 172 | value = code_ptr[1]; 173 | 174 | code_ptr += 2; 175 | 176 | cheat_opcode = address >> 28; 177 | address &= 0xFFFFFFF; 178 | 179 | switch(cheat_opcode) 180 | { 181 | case 0x0: 182 | write_memory8(address, value); 183 | break; 184 | 185 | case 0x1: 186 | write_memory16(address, value); 187 | break; 188 | 189 | case 0x2: 190 | write_memory32(address, value); 191 | break; 192 | 193 | case 0x3: 194 | { 195 | u32 num_addresses = address & 0xFFFF; 196 | u32 address1, address2; 197 | u32 i2; 198 | 199 | for(i2 = 0; i2 < num_addresses; i2++) 200 | { 201 | address1 = code_ptr[0]; 202 | address2 = code_ptr[1]; 203 | code_ptr += 2; 204 | i++; 205 | 206 | write_memory32(address1, value); 207 | if(address2 != 0) 208 | write_memory32(address2, value); 209 | } 210 | break; 211 | } 212 | 213 | // ROM patch not supported yet 214 | case 0x6: 215 | break; 216 | 217 | // GS button down not supported yet 218 | case 0x8: 219 | break; 220 | 221 | // Reencryption (DEADFACE) not supported yet 222 | case 0xD: 223 | if(read_memory16(address) != (value & 0xFFFF)) 224 | { 225 | code_ptr += 2; 226 | i++; 227 | } 228 | break; 229 | 230 | case 0xE: 231 | if(read_memory16(value & 0xFFFFFFF) != (address & 0xFFFF)) 232 | { 233 | u32 skip = ((address >> 16) & 0x03); 234 | code_ptr += skip * 2; 235 | i += skip; 236 | } 237 | break; 238 | 239 | // Hook routine not supported yet (not important??) 240 | case 0x0F: 241 | break; 242 | } 243 | } 244 | } 245 | 246 | // These are especially incomplete. 247 | 248 | void process_cheat_gs3(cheat_type *cheat) 249 | { 250 | u32 cheat_opcode; 251 | u32 *code_ptr = cheat->cheat_codes; 252 | u32 address, value; 253 | u32 i; 254 | 255 | for(i = 0; i < cheat->num_cheat_lines; i++) 256 | { 257 | address = code_ptr[0]; 258 | value = code_ptr[1]; 259 | 260 | code_ptr += 2; 261 | 262 | cheat_opcode = address >> 28; 263 | address &= 0xFFFFFFF; 264 | 265 | switch(cheat_opcode) 266 | { 267 | case 0x0: 268 | cheat_opcode = address >> 24; 269 | address = (address & 0xFFFFF) + ((address << 4) & 0xF000000); 270 | 271 | switch(cheat_opcode) 272 | { 273 | case 0x0: 274 | { 275 | u32 iterations = value >> 24; 276 | u32 i2; 277 | 278 | value &= 0xFF; 279 | 280 | for(i2 = 0; i2 <= iterations; i2++, address++) 281 | { 282 | write_memory8(address, value); 283 | } 284 | break; 285 | } 286 | 287 | case 0x2: 288 | { 289 | u32 iterations = value >> 16; 290 | u32 i2; 291 | 292 | value &= 0xFFFF; 293 | 294 | for(i2 = 0; i2 <= iterations; i2++, address += 2) 295 | { 296 | write_memory16(address, value); 297 | } 298 | break; 299 | } 300 | 301 | case 0x4: 302 | write_memory32(address, value); 303 | break; 304 | } 305 | break; 306 | 307 | case 0x4: 308 | cheat_opcode = address >> 24; 309 | address = (address & 0xFFFFF) + ((address << 4) & 0xF000000); 310 | 311 | switch(cheat_opcode) 312 | { 313 | case 0x0: 314 | address = read_memory32(address) + (value >> 24); 315 | write_memory8(address, value & 0xFF); 316 | break; 317 | 318 | case 0x2: 319 | address = read_memory32(address) + ((value >> 16) * 2); 320 | write_memory16(address, value & 0xFFFF); 321 | break; 322 | 323 | case 0x4: 324 | address = read_memory32(address); 325 | write_memory32(address, value); 326 | break; 327 | 328 | } 329 | break; 330 | 331 | case 0x8: 332 | cheat_opcode = address >> 24; 333 | address = (address & 0xFFFFF) + ((address << 4) & 0xF000000); 334 | 335 | switch(cheat_opcode) 336 | { 337 | case 0x0: 338 | value = (value & 0xFF) + read_memory8(address); 339 | write_memory8(address, value); 340 | break; 341 | 342 | case 0x2: 343 | value = (value & 0xFFFF) + read_memory16(address); 344 | write_memory16(address, value); 345 | break; 346 | 347 | case 0x4: 348 | value = value + read_memory32(address); 349 | write_memory32(address, value); 350 | break; 351 | } 352 | break; 353 | 354 | case 0xC: 355 | cheat_opcode = address >> 24; 356 | address = (address & 0xFFFFFF) + 0x4000000; 357 | 358 | switch(cheat_opcode) 359 | { 360 | case 0x6: 361 | write_memory16(address, value); 362 | break; 363 | 364 | case 0x7: 365 | write_memory32(address, value); 366 | break; 367 | } 368 | break; 369 | } 370 | } 371 | } 372 | 373 | 374 | void process_cheats() 375 | { 376 | u32 i; 377 | 378 | for(i = 0; i < num_cheats; i++) 379 | { 380 | if(cheats[i].cheat_active) 381 | { 382 | switch(cheats[i].cheat_variant) 383 | { 384 | case CHEAT_TYPE_GAMESHARK_V1: 385 | process_cheat_gs1(cheats + i); 386 | break; 387 | 388 | case CHEAT_TYPE_GAMESHARK_V3: 389 | process_cheat_gs3(cheats + i); 390 | break; 391 | } 392 | } 393 | } 394 | } 395 | -------------------------------------------------------------------------------- /cheats.h: -------------------------------------------------------------------------------- 1 | /* gameplaySP 2 | * 3 | * Copyright (C) 2006 Exophase 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License as 7 | * published by the Free Software Foundation; either version 2 of 8 | * the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #define CHEAT_NAME_LENGTH 17 21 | 22 | typedef enum 23 | { 24 | CHEAT_TYPE_GAMESHARK_V1, 25 | CHEAT_TYPE_GAMESHARK_V3, 26 | CHEAT_TYPE_INVALID 27 | } cheat_variant_enum; 28 | 29 | typedef struct 30 | { 31 | u8 cheat_name[CHEAT_NAME_LENGTH]; 32 | u32 cheat_active; 33 | u32 cheat_codes[256]; 34 | u32 num_cheat_lines; 35 | cheat_variant_enum cheat_variant; 36 | } cheat_type; 37 | 38 | void process_cheats(); 39 | void add_cheats(u8 *cheats_filename); 40 | 41 | #define MAX_CHEATS 8 42 | 43 | extern cheat_type cheats[MAX_CHEATS]; 44 | extern u32 num_cheats; 45 | -------------------------------------------------------------------------------- /common.h: -------------------------------------------------------------------------------- 1 | /* gameplaySP 2 | * 3 | * Copyright (C) 2006 Exophase 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License as 7 | * published by the Free Software Foundation; either version 2 of 8 | * the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #ifndef COMMON_H 21 | #define COMMON_H 22 | 23 | #define ror(dest, value, shift) \ 24 | dest = ((value) >> shift) | ((value) << (32 - shift)) \ 25 | 26 | // Huge thanks to pollux for the heads up on using native file I/O 27 | // functions on PSP for vastly improved memstick performance. 28 | 29 | #define file_write_mem(filename_tag, buffer, size) \ 30 | { \ 31 | memcpy(write_mem_ptr, buffer, size); \ 32 | write_mem_ptr += size; \ 33 | } \ 34 | 35 | #define file_write_mem_array(filename_tag, array) \ 36 | file_write_mem(filename_tag, array, sizeof(array)) \ 37 | 38 | #define file_write_mem_variable(filename_tag, variable) \ 39 | file_write_mem(filename_tag, &variable, sizeof(variable)) \ 40 | 41 | #ifdef PSP_BUILD 42 | #define fastcall 43 | 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | 52 | #define function_cc 53 | 54 | #define convert_palette(value) \ 55 | value = ((value & 0x7FE0) << 1) | (value & 0x1F) \ 56 | 57 | #define psp_file_open_read PSP_O_RDONLY 58 | #define psp_file_open_write (PSP_O_CREAT | PSP_O_WRONLY | PSP_O_TRUNC) 59 | 60 | #define file_open(filename_tag, filename, mode) \ 61 | s32 filename_tag = sceIoOpen(filename, psp_file_open_##mode, 0777) \ 62 | 63 | #define file_check_valid(filename_tag) \ 64 | (filename_tag >= 0) \ 65 | 66 | #define file_close(filename_tag) \ 67 | sceIoClose(filename_tag) \ 68 | 69 | #define file_read(filename_tag, buffer, size) \ 70 | sceIoRead(filename_tag, buffer, size) \ 71 | 72 | #define file_write(filename_tag, buffer, size) \ 73 | sceIoWrite(filename_tag, buffer, size) \ 74 | 75 | #define file_seek(filename_tag, offset, type) \ 76 | sceIoLseek(filename_tag, offset, PSP_##type) \ 77 | 78 | #define file_tag_type s32 79 | #else 80 | #include "SDL.h" 81 | 82 | #ifndef _arch_dreamcast 83 | #define function_cc __attribute__((regparm(2))) 84 | #else 85 | #define function_cc 86 | #endif 87 | 88 | typedef unsigned char u8; 89 | typedef signed char s8; 90 | typedef unsigned short int u16; 91 | typedef signed short int s16; 92 | typedef unsigned int u32; 93 | typedef signed int s32; 94 | typedef unsigned long long int u64; 95 | typedef signed long long int s64; 96 | 97 | #define convert_palette(value) \ 98 | value = ((value & 0x1F) << 11) | ((value & 0x03E0) << 1) | (value >> 10) \ 99 | 100 | #define stdio_file_open_read "rb" 101 | #define stdio_file_open_write "wb" 102 | 103 | #define file_open(filename_tag, filename, mode) \ 104 | FILE *filename_tag = fopen(filename, stdio_file_open_##mode) \ 105 | 106 | #define file_check_valid(filename_tag) \ 107 | (filename_tag) \ 108 | 109 | #define file_close(filename_tag) \ 110 | fclose(filename_tag) \ 111 | 112 | #define file_read(filename_tag, buffer, size) \ 113 | fread(buffer, size, 1, filename_tag) \ 114 | 115 | #define file_write(filename_tag, buffer, size) \ 116 | fwrite(buffer, size, 1, filename_tag) \ 117 | 118 | #define file_seek(filename_tag, offset, type) \ 119 | fseek(filename_tag, offset, type) \ 120 | 121 | #define file_tag_type FILE * 122 | 123 | #endif 124 | 125 | // These must be variables, not constants. 126 | 127 | #define file_read_variable(filename_tag, variable) \ 128 | file_read(filename_tag, &variable, sizeof(variable)) \ 129 | 130 | #define file_write_variable(filename_tag, variable) \ 131 | file_write(filename_tag, &variable, sizeof(variable)) \ 132 | 133 | // These must be statically declared arrays (ie, global or on the stack, 134 | // not dynamically allocated on the heap) 135 | 136 | #define file_read_array(filename_tag, array) \ 137 | file_read(filename_tag, array, sizeof(array)) \ 138 | 139 | #define file_write_array(filename_tag, array) \ 140 | file_write(filename_tag, array, sizeof(array)) \ 141 | 142 | 143 | 144 | typedef u32 fixed16_16; 145 | 146 | #define float_to_fp16_16(value) \ 147 | (fixed16_16)((value) * 65536.0) \ 148 | 149 | #define fp16_16_to_float(value) \ 150 | (float)((value) / 65536.0) \ 151 | 152 | #define u32_to_fp16_16(value) \ 153 | ((value) << 16) \ 154 | 155 | #define fp16_16_to_u32(value) \ 156 | ((value) >> 16) \ 157 | 158 | #define fp16_16_fractional_part(value) \ 159 | ((value) & 0xFFFF) \ 160 | 161 | #define fixed_div(numerator, denominator, bits) \ 162 | (((numerator * (1 << bits)) + (denominator / 2)) / denominator) \ 163 | 164 | #define address8(base, offset) \ 165 | *((u8 *)((u8 *)base + (offset))) \ 166 | 167 | #define address16(base, offset) \ 168 | *((u16 *)((u8 *)base + (offset))) \ 169 | 170 | #define address32(base, offset) \ 171 | *((u32 *)((u8 *)base + (offset))) \ 172 | 173 | #include 174 | #include 175 | #include 176 | #include 177 | #include 178 | #include "SDL.h" 179 | #include "cpu.h" 180 | #include "memory.h" 181 | #include "video.h" 182 | #include "input.h" 183 | #include "sound.h" 184 | #include "main.h" 185 | #include "gui.h" 186 | #include "zip.h" 187 | #include "cheats.h" 188 | 189 | #ifdef PSP_BUILD 190 | #define printf pspDebugScreenPrintf 191 | #endif 192 | 193 | #endif 194 | 195 | -------------------------------------------------------------------------------- /cpu.h: -------------------------------------------------------------------------------- 1 | /* gameplaySP 2 | * 3 | * Copyright (C) 2006 Exophase 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License as 7 | * published by the Free Software Foundation; either version 2 of 8 | * the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #ifndef CPU_H 21 | #define CPU_H 22 | 23 | void init_cpu(); 24 | // System mode and user mode are represented as the same here 25 | 26 | typedef enum 27 | { 28 | MODE_USER, 29 | MODE_IRQ, 30 | MODE_FIQ, 31 | MODE_SUPERVISOR, 32 | MODE_ABORT, 33 | MODE_UNDEFINED, 34 | MODE_INVALID 35 | } cpu_mode_type; 36 | 37 | typedef enum 38 | { 39 | CPU_ALERT_NONE, 40 | CPU_ALERT_HALT, 41 | CPU_ALERT_SMC, 42 | CPU_ALERT_IRQ 43 | } cpu_alert_type; 44 | 45 | typedef enum 46 | { 47 | CPU_ACTIVE, 48 | CPU_HALT, 49 | CPU_STOP 50 | } cpu_halt_type; 51 | 52 | typedef enum 53 | { 54 | IRQ_NONE = 0x0000, 55 | IRQ_VBLANK = 0x0001, 56 | IRQ_HBLANK = 0x0002, 57 | IRQ_VCOUNT = 0x0004, 58 | IRQ_TIMER0 = 0x0008, 59 | IRQ_TIMER1 = 0x0010, 60 | IRQ_TIMER2 = 0x0020, 61 | IRQ_TIMER3 = 0x0040, 62 | IRQ_SERIAL = 0x0080, 63 | IRQ_DMA0 = 0x0100, 64 | IRQ_DMA1 = 0x0200, 65 | IRQ_DMA2 = 0x0400, 66 | IRQ_DMA3 = 0x0800, 67 | IRQ_KEYPAD = 0x1000, 68 | IRQ_GAMEPAK = 0x2000, 69 | } irq_type; 70 | 71 | typedef enum 72 | { 73 | REG_SP = 13, 74 | REG_LR = 14, 75 | REG_PC = 15, 76 | REG_N_FLAG = 16, 77 | REG_Z_FLAG = 17, 78 | REG_C_FLAG = 18, 79 | REG_V_FLAG = 19, 80 | REG_CPSR = 20, 81 | REG_SAVE = 21, 82 | REG_SAVE2 = 22, 83 | REG_SAVE3 = 23, 84 | CPU_MODE = 29, 85 | CPU_HALT_STATE = 30, 86 | CHANGED_PC_STATUS = 31 87 | } ext_reg_numbers; 88 | 89 | typedef enum 90 | { 91 | STEP, 92 | PC_BREAKPOINT, 93 | VCOUNT_BREAKPOINT, 94 | Z_BREAKPOINT, 95 | COUNTDOWN_BREAKPOINT, 96 | COUNTDOWN_BREAKPOINT_B, 97 | STEP_RUN, 98 | RUN 99 | } debug_state; 100 | 101 | typedef enum 102 | { 103 | TRANSLATION_REGION_RAM, 104 | TRANSLATION_REGION_ROM, 105 | TRANSLATION_REGION_BIOS 106 | } translation_region_type; 107 | 108 | extern debug_state current_debug_state; 109 | extern u32 instruction_count; 110 | extern u32 last_instruction; 111 | 112 | u32 function_cc step_debug(u32 pc, u32 cycles); 113 | u32 execute_arm(u32 cycles); 114 | void raise_interrupt(irq_type irq_raised); 115 | 116 | u32 function_cc execute_load_u8(u32 address); 117 | u32 function_cc execute_load_u16(u32 address); 118 | u32 function_cc execute_load_u32(u32 address); 119 | u32 function_cc execute_load_s8(u32 address); 120 | u32 function_cc execute_load_s16(u32 address); 121 | void function_cc execute_store_u8(u32 address, u32 source); 122 | void function_cc execute_store_u16(u32 address, u32 source); 123 | void function_cc execute_store_u32(u32 address, u32 source); 124 | void function_cc execute_store_u8_no_smc(u32 address, u32 source); 125 | void function_cc execute_store_u16_no_smc(u32 address, u32 source); 126 | void function_cc execute_store_u32_no_smc(u32 address, u32 source); 127 | u32 function_cc execute_arm_translate(u32 cycles); 128 | void init_translater(); 129 | void cpu_write_mem_savestate(file_tag_type savestate_file); 130 | void cpu_read_savestate(file_tag_type savestate_file); 131 | 132 | u8 function_cc *block_lookup_address_arm(u32 pc); 133 | u8 function_cc *block_lookup_address_thumb(u32 pc); 134 | s32 translate_block_arm(u32 pc, translation_region_type translation_region, 135 | u32 smc_enable); 136 | s32 translate_block_thumb(u32 pc, translation_region_type translation_region, 137 | u32 smc_enable); 138 | 139 | #define ROM_TRANSLATION_CACHE_SIZE (1024 * 512 * 4) 140 | #define RAM_TRANSLATION_CACHE_SIZE (1024 * 384) 141 | #define BIOS_TRANSLATION_CACHE_SIZE (1024 * 128) 142 | #define TRANSLATION_CACHE_LIMIT_THRESHOLD (1024) 143 | 144 | extern u8 rom_translation_cache[ROM_TRANSLATION_CACHE_SIZE]; 145 | extern u8 ram_translation_cache[RAM_TRANSLATION_CACHE_SIZE]; 146 | extern u8 bios_translation_cache[BIOS_TRANSLATION_CACHE_SIZE]; 147 | extern u8 *rom_translation_ptr; 148 | extern u8 *ram_translation_ptr; 149 | extern u8 *bios_translation_ptr; 150 | 151 | #define MAX_TRANSLATION_GATES 8 152 | 153 | extern u32 idle_loop_target_pc; 154 | extern u32 force_pc_update_target; 155 | extern u32 iwram_stack_optimize; 156 | extern u32 allow_smc_ram_u8; 157 | extern u32 allow_smc_ram_u16; 158 | extern u32 allow_smc_ram_u32; 159 | extern u32 direct_map_vram; 160 | extern u32 translation_gate_targets; 161 | extern u32 translation_gate_target_pc[MAX_TRANSLATION_GATES]; 162 | 163 | #define ROM_BRANCH_HASH_SIZE (1024 * 64) 164 | 165 | extern u32 *rom_branch_hash[ROM_BRANCH_HASH_SIZE]; 166 | 167 | void flush_translation_cache_rom(); 168 | void flush_translation_cache_ram(); 169 | void flush_translation_cache_bios(); 170 | void dump_translation_cache(); 171 | 172 | extern u32 reg_mode[7][7]; 173 | extern u32 spsr[6]; 174 | extern cpu_mode_type cpu_mode; 175 | extern cpu_halt_type cpu_halt; 176 | 177 | extern u32 cpu_modes[32]; 178 | extern const u32 psr_masks[16]; 179 | 180 | extern u32 breakpoint_value; 181 | 182 | extern u32 memory_region_access_read_u8[16]; 183 | extern u32 memory_region_access_read_s8[16]; 184 | extern u32 memory_region_access_read_u16[16]; 185 | extern u32 memory_region_access_read_s16[16]; 186 | extern u32 memory_region_access_read_u32[16]; 187 | extern u32 memory_region_access_write_u8[16]; 188 | extern u32 memory_region_access_write_u16[16]; 189 | extern u32 memory_region_access_write_u32[16]; 190 | extern u32 memory_reads_u8; 191 | extern u32 memory_reads_s8; 192 | extern u32 memory_reads_u16; 193 | extern u32 memory_reads_s16; 194 | extern u32 memory_reads_u32; 195 | extern u32 memory_writes_u8; 196 | extern u32 memory_writes_u16; 197 | extern u32 memory_writes_u32; 198 | 199 | #endif 200 | -------------------------------------------------------------------------------- /dc/Makefile: -------------------------------------------------------------------------------- 1 | # gpSP 2 | # DC porting by Troy Davis (GPF) 3 | 4 | TARGET = gdC.elf 5 | OBJS = sh4_stub.o ../main.o ../cpu_threaded.o ../cpu.o ../memory.o ../video.o ../input.o ../sound.o \ 6 | ../gui.o ../zip.o ../cheats.o romdisk.o 7 | 8 | KOS_ROMDISK_DIR = romdisk 9 | 10 | include $(KOS_BASE)/Makefile.rules 11 | 12 | KOS_CFLAGS += -D_arch_dreamcast=1 \ 13 | -I../dc \ 14 | -I.. \ 15 | -I$(KOS_BASE)/addons/include \ 16 | -I$(KOS_BASE)/addons/include/SDL \ 17 | -I$(KOS_BASE)/../kos-ports/include/zlib \ 18 | -I$(KOS_BASE)/../kos-ports/include/png 19 | 20 | all: rm-elf $(TARGET) 21 | 22 | clean: rm-elf 23 | -rm -f $(OBJS) 24 | 25 | rm-elf: 26 | -rm -f $(TARGET) romdisk.* 27 | 28 | $(TARGET): $(OBJS) 29 | kos-cc -o $(TARGET) $(OBJS) -L$(KOS_BASE)/lib/dreamcast -L$(KOS_BASE)/addons/lib/dreamcast -L$(KOS_BASE)/../kos-ports/lib \ 30 | -lz -lm -lSDL $(KOS_LIBS) 31 | 32 | run: $(TARGET) 33 | $(KOS_LOADER) $(TARGET) 34 | 35 | dist: $(TARGET) 36 | -rm -f $(OBJS) romdisk.img 37 | $(KOS_STRIP) $(TARGET) 38 | 39 | # AR = ar 40 | # AR_FLAGS = cru 41 | # RANLIB = ranlib 42 | 43 | # INC=-I. 44 | 45 | # OPT= -O3 -Wall -ffast-math -funroll-loops -fstrict-aliasing -fexpensive-optimizations -falign-functions -fweb -frename-registers -fomit-frame-pointer -finline -finline-functions -fno-builtin -fno-common 46 | 47 | 48 | # OPT2 = -O9 -fomit-frame-pointer -fno-ident -freorder-blocks -funsigned-char -funsigned-char -funroll-all-loops -frerun-loop-opt -falign-loops -fstrict-aliasing 49 | 50 | # OPT3 = -O2 -Wall -ffast-math -fno-optimize-sibling-calls -fno-builtin -fno-strict-aliasing 51 | # OPT4 = -DFRAME_POINTER -g3 -O0 -fno-eliminate-unused-debug-types 52 | # OPT5 = -Wno-implicit-function-declaration -Wno-implicit-int -Wno-return-mismatch 53 | # #KOS_CFLAGS += $(INC) $(OPT2) 54 | # KOS_CFLAGS = $(INC) -ml -m4-single-only -D_arch_dreamcast -D_arch_sub_pristine \ 55 | # $(OPT5) \ 56 | # -I$(KOS_BASE)/../../sh-elf/sh-elf/include -I$(KOS_BASE)/include -I$(KOS_BASE)/kernel/arch/dreamcast/include -I$(KOS_BASE)/addons/include -I$(KOS_BASE)/addons/include/SDL -I$(KOS_BASE)/../kos-ports/include/zlib -I$(KOS_BASE)/../kos-ports/include/png 57 | 58 | 59 | # KOS_CPPFLAGS+= ${KOS_CFLAGS} 60 | 61 | 62 | 63 | 64 | # TARGET = gdC.elf 65 | 66 | # .PHONY: all all-before all-after clean clean-custom 67 | 68 | # all: all-before $(TARGET) all-after 69 | 70 | # include dreamcast.mak 71 | 72 | # OBJS = ../main.o ../cpu.o ../memory.o ../video.o ../input.o ../sound.o \ 73 | # ../gui.o ../zip.o ../cheats.o #x86_stub.o ../cpu_threaded.o 74 | 75 | # include $(KOS_BASE)/Makefile.rules 76 | 77 | # clean: 78 | # -rm -f $(TARGET) $(OBJS) romdisk.* 79 | 80 | # rm-elf: 81 | # -rm -f $(TARGET) romdisk.* 82 | 83 | # $(TARGET): $(OBJS) $(PROBJS) romdisk.o 84 | # $(KOS_CC) $(KOS_CFLAGS) $(KOS_LDFLAGS) -o $(TARGET) $(KOS_START) \ 85 | # $(OBJS) $(PROBJS) romdisk.o $(OBJEXTRA) -L$(KOS_BASE)/lib -lgcc -lz -lm -lSDL -lstdc++ $(KOS_LIBS) 86 | 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /dc/cd/IP.BIN: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GPF/gPSPDC/9887759aee122eefff3cab6d7d9109ed34de60ee/dc/cd/IP.BIN -------------------------------------------------------------------------------- /dc/cd/gbaDC/DangerousXmas.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GPF/gPSPDC/9887759aee122eefff3cab6d7d9109ed34de60ee/dc/cd/gbaDC/DangerousXmas.bin -------------------------------------------------------------------------------- /dc/cd/gbaDC/Doom (USA, Europe).cht: -------------------------------------------------------------------------------- 1 | PAR_V3 (M) 2 | 6d760988 a0dd7658 3 | 3256eba3 1ec6f7b9 4 | 5 | 6 | PAR_V3 Infinite Bullets 7 | 6e98adf6 91ebd69e 8 | 9 | 10 | PAR_V3 Infinite Shells 11 | d5b70882 c8d9e49f 12 | 13 | 14 | PAR_V3 Infinite Cells 15 | 392a958b 4b509c5c 16 | 17 | 18 | PAR_V3 Infinite Rockets 19 | d2f23841 58d58dc9 20 | 21 | 22 | PAR_V3 Infinite Armor 23 | 677caf63 825f5641 24 | 25 | 26 | PAR_V3 Have Blue Key 27 | 74a5f4e6 67a38db9 28 | 29 | 30 | PAR_V3 Have Yellow Key 31 | 28212a5c b5b45143 32 | 33 | 34 | PAR_V3 Have Red Key 35 | d1ba5c78 13135a2d 36 | 37 | 38 | PAR_V3 Have Shotgun 39 | b2f31572 ed12ac6b 40 | 41 | 42 | PAR_V3 Have Chaingun 43 | 1dc47422 e229e2e8 44 | 45 | 46 | PAR_V3 Have Rocket Launcher 47 | 661e5e26 f3e7a698 48 | 49 | 50 | PAR_V3 Have Plasma Gun 51 | 03a0ad30 4ff3fad2 52 | 53 | 54 | PAR_V3 Have BFG 9000 55 | ebe16df2 94b61a2b 56 | 57 | 58 | PAR_V3 Have Chainsaw 59 | 31e57e32 e9015b1d 60 | 61 | 62 | PAR_V3 Have Radiation Suit 63 | 3d13628d 20daf6ea 64 | 65 | 66 | PAR_V3 God Mode 67 | 2b44d892 822a3529 -------------------------------------------------------------------------------- /dc/cd/gbaDC/Super Mario Advance (USA, Europe).cht: -------------------------------------------------------------------------------- 1 | PAR_V3 (M) 2 | 9f5c79e3 292e8a5b 3 | 1802dcf0 525fe061 4 | 5 | 6 | PAR_V3 Inf Lives 7 | 8c706ce2 7289b36d 8 | 9 | 10 | PAR_V3 Max Hearts 11 | 42d8dcb7 16e09d2c 12 | 13 | 14 | PAR_V3 Inf Star Power 15 | 831814ac 06354ae1 16 | 17 | 18 | PAR_V3 Always Big Mario 19 | adf2a0ee 94504fb2 20 | 21 | 22 | PAR_V3 Always Power Jump 23 | d633983a 476cc5f5 24 | 25 | 26 | PAR_V3 Infinite Float 27 | 28d79342 8b546cf3 28 | 29 | 30 | PAR_V3 Have All 5 Coins 31 | 7961aed6 dae39f98 32 | 33 | 34 | PAR_V3 Max Score 35 | 0e1ce091 424397dc 36 | 37 | 38 | PAR_V3 Max Score P1 Classic 39 | 4cb2957d 8be9492f 40 | 41 | 42 | PAR_V3 Inf Lives Classic 43 | a47b5f6f 38caf74f 44 | 45 | 46 | PAR_V3 Start On 1-2 47 | d016c98f e7b80a66 48 | 49 | 50 | PAR_V3 Start On 1-3 51 | b0973511 bd18403b 52 | 53 | 54 | PAR_V3 Start On 2-1 55 | 783d2499 2789e78f 56 | 57 | 58 | PAR_V3 Start On 2-2 59 | 4f8cb2b3 dfff0e53 60 | 61 | 62 | PAR_V3 Start On 2-3 63 | 4be13681 b84c3c24 64 | 65 | 66 | PAR_V3 Start On 3-1 67 | 697a1700 dd9a6de0 68 | 69 | 70 | PAR_V3 Start On 3-2 71 | ffe2291d cd210983 72 | 73 | 74 | PAR_V3 Start On 3-3 75 | 2c047ec2 c15ce453 76 | 77 | 78 | PAR_V3 Start On 4-1 79 | 344d7dbc 77a72868 80 | 81 | 82 | PAR_V3 Start On 4-2 83 | f0de95a8 df36cfc5 84 | 85 | 86 | PAR_V3 Start On 4-3 87 | db0d21d5 1cf8602a 88 | 89 | 90 | PAR_V3 Start On 5-1 91 | bee06b2e a1bcd8d6 92 | 93 | 94 | PAR_V3 Start On 5-2 95 | c0f438cb 1cfdb481 96 | 97 | 98 | PAR_V3 Start On 5-3 99 | add62140 d20f357b 100 | 101 | 102 | PAR_V3 Start On 6-1 103 | 8a0996a6 b02dbf1d 104 | 105 | 106 | PAR_V3 Start On 6-2 107 | 8466a731 3177ae04 108 | 109 | 110 | PAR_V3 Start On 6-3 111 | ce10190d be694c61 112 | 113 | 114 | PAR_V3 Start On 7-1 115 | 1af191dc 548fb12c 116 | 117 | 118 | PAR_V3 Start On 7-2 119 | 1af191dc 548fb12c 120 | -------------------------------------------------------------------------------- /dc/cd/gbaDC/game_config.txt: -------------------------------------------------------------------------------- 1 | # gpSP game settings database 2 | # This file is meant to be edited in plain text, with a normal editor. 3 | # game_name, game_code, and vender_code can be found in the game's header. 4 | # All three must match for the game to be used, and those setting must be in 5 | # that order. Be sure to use [!] ROMs (verified by GoodGBA) when building 6 | # this list. Right now I don't know how much overlap there is between 7 | # different region games. 8 | 9 | # Find the game identification values by opening the ROM in a hex editor 10 | # and looking at the following locations: 11 | 12 | # 0xA0: name, 12 characters 13 | # 0xAC: code, 4 characters 14 | # 0xB0: vender, 2 characters 15 | 16 | # Many games should run okay with nothing here, but those that have idle 17 | # loops will run very slowly. To eliminate idle loops you must find a 18 | # branch instruction that will result in a loop until something in the 19 | # hardware changes, like vsync flagging or an interrupt going off. Then 20 | # set "idle_loop_eliminate_target" to the location of that branch 21 | # instruction. 22 | 23 | # By default "iwram_stack_optimize" is set to yes, but this breaks some 24 | # games (like Kirby: Nightmare in Dreamland). If a game doesn't work you 25 | # can try setting it to no. 26 | 27 | # Everything here is case sensitive. Don't mess with this file unless 28 | # you know what you're doing - if in doubt sooner ask someone who does. 29 | 30 | # I mainly focus on USA versions, so try those first. And, just because 31 | # a game is on here doesn't mean the game actually works in the current 32 | # version. :/ 33 | 34 | # If a game uses 128KB flash ROMs set the option flash_rom_type = 128KB 35 | # for it. 36 | 37 | # Castlevania: Circle of the Moon (U) 38 | game_name = DRACULA AGB1 39 | game_code = AAME 40 | vender_code = A4 41 | idle_loop_eliminate_target = 080003d2 42 | 43 | # Megaman Battle Network (U) 44 | game_name = MEGAMAN_BN 45 | game_code = AREE 46 | vender_code = 08 47 | idle_loop_eliminate_target = 08000338 48 | 49 | # Megaman Battle Network 2 (U) 50 | game_name = MEGAMAN_EXE2 51 | game_code = AE2E 52 | vender_code = 08 53 | idle_loop_eliminate_target = 08000358 54 | 55 | # Megaman Battle Network 3 White (U) 56 | game_name = MEGA_EXE3_WH 57 | game_code = A6BE 58 | vender_code = 08 59 | idle_loop_eliminate_target = 0800036c 60 | 61 | # Megaman Battle Network 3 Blue (U) 62 | game_name = MEGA_EXE3_BL 63 | game_code = A3XE 64 | vender_code = 08 65 | idle_loop_eliminate_target = 0800036c 66 | 67 | # Megaman Battle Network 4 Red Sun (U) 68 | game_name = MEGAMANBN4RS 69 | game_code = B4WE 70 | vender_code = 08 71 | idle_loop_eliminate_target = 080003a6 72 | 73 | # Megaman Battle Network 4 Blue Moon (U) 74 | game_name = MEGAMANBN4BM 75 | game_code = B4BE 76 | vender_code = 08 77 | idle_loop_eliminate_target = 080003a6 78 | 79 | # Megaman Battle Network 5 Team Protoman (U) 80 | game_name = MEGAMAN5_TP_ 81 | game_code = BRBE 82 | vender_code = 08 83 | idle_loop_eliminate_target = 080003ca 84 | 85 | # Megaman Battle Network 5 Team Colonel (U) 86 | game_name = MEGAMAN5_TC_ 87 | game_code = BRKE 88 | vender_code = 08 89 | idle_loop_eliminate_target = 080003ca 90 | 91 | # Megaman Battle Network 6 Cybeast Gregar (U) 92 | game_name = MEGAMAN6_GXX 93 | game_code = BR5E 94 | vender_code = 08 95 | idle_loop_eliminate_target = 080003da 96 | 97 | # Megaman Zero (U/E) 98 | game_name = MEGAMAN ZERO 99 | game_code = AZCE 100 | vender_code = 08 101 | idle_loop_eliminate_target = 080004ee 102 | 103 | # Megaman Zero 2 (U) 104 | game_name = MEGAMANZERO2 105 | game_code = A62E 106 | vender_code = 08 107 | idle_loop_eliminate_target = 08000664 108 | 109 | # Megaman Zero 3 (U) 110 | game_name = MEGAMANZERO3 111 | game_code = BZ3E 112 | vender_code = 08 113 | idle_loop_eliminate_target = 08001a08 114 | 115 | # Megaman Zero 4 (U) 116 | game_name = MEGAMANZERO4 117 | game_code = B4ZP 118 | vender_code = 08 119 | idle_loop_eliminate_target = 0800090c 120 | 121 | # Kirby: Nightmare in Dreamland (U) 122 | game_name = AGB KIRBY DX 123 | game_code = A7KE 124 | vender_code = 01 125 | idle_loop_eliminate_target = 08000fae 126 | iwram_stack_optimize = no 127 | 128 | # Super Mario Advance (U) 129 | game_name = SUPER MARIOA 130 | game_code = AMZE 131 | vender_code = 01 132 | idle_loop_eliminate_target = 08001cf2 133 | 134 | # Super Mario Advance 2 (U) 135 | game_name = SUPER MARIOB 136 | game_code = AA2E 137 | vender_code = 01 138 | idle_loop_eliminate_target = 08000534 139 | 140 | # Super Mario Advance 3 (U) 141 | game_name = SUPER MARIOC 142 | game_code = A3AE 143 | vender_code = 01 144 | idle_loop_eliminate_target = 08002ba4 145 | 146 | # Super Mario Advance 4 (U) 147 | game_name = SUPER MARIOD 148 | game_code = AX4E 149 | vender_code = 01 150 | idle_loop_eliminate_target = 08000732 151 | flash_rom_type = 128KB 152 | 153 | # Super Mario Advance 4 (J) 154 | game_name = SUPER MARIOD 155 | game_code = AX4J 156 | vender_code = 01 157 | idle_loop_eliminate_target = 08000732 158 | flash_rom_type = 128KB 159 | 160 | # Super Mario Advance 4 (E) 161 | game_name = SUPER MARIOD 162 | game_code = AX4P 163 | vender_code = 01 164 | idle_loop_eliminate_target = 08000732 165 | flash_rom_type = 128KB 166 | 167 | # Advance Wars (U) 168 | # This one was really annoying to find, I hope it's okay.. there 169 | # might be a better one somewhere. 170 | game_name = ADVANCEWARS 171 | game_code = AWRE 172 | vender_code = 01 173 | idle_loop_eliminate_target = 0803880a 174 | 175 | # Pokemon Emerald (E/U) 176 | # I don't know why this has an idle loop when Ruby doesn't.... 177 | game_name = POKEMON EMER 178 | game_code = BPEE 179 | vender_code = 01 180 | idle_loop_eliminate_target = 080008ce 181 | flash_rom_type = 128KB 182 | 183 | # Pokemon Emerald (J) 184 | game_name = POKEMON EMER 185 | game_code = BPEJ 186 | vender_code = 01 187 | idle_loop_eliminate_target = 080008ce 188 | flash_rom_type = 128KB 189 | 190 | # Pokemon Emerald (G) 191 | game_name = POKEMON EMER 192 | game_code = BPED 193 | vender_code = 01 194 | idle_loop_eliminate_target = 080008ce 195 | flash_rom_type = 128KB 196 | 197 | # Pokemon Emerald (F) 198 | game_name = POKEMON EMER 199 | game_code = BPEF 200 | vender_code = 01 201 | idle_loop_eliminate_target = 080008ce 202 | flash_rom_type = 128KB 203 | 204 | # Pokemon Emerald (S) 205 | game_name = POKEMON EMER 206 | game_code = BPES 207 | vender_code = 01 208 | idle_loop_eliminate_target = 080008ce 209 | flash_rom_type = 128KB 210 | 211 | # Pokemon Emerald (I) 212 | game_name = POKEMON EMER 213 | game_code = BPEI 214 | vender_code = 01 215 | idle_loop_eliminate_target = 080008ce 216 | flash_rom_type = 128KB 217 | 218 | # Pokemon Sapphire (U) 219 | game_name = POKEMON SAPP 220 | game_code = AXPE 221 | vender_code = 01 222 | flash_rom_type = 128KB 223 | 224 | # Pokemon Sapphire (J) 225 | game_name = POKEMON SAPP 226 | game_code = AXPJ 227 | vender_code = 01 228 | flash_rom_type = 128KB 229 | 230 | # Pokemon Sapphire (G) 231 | game_name = POKEMON SAPP 232 | game_code = AXPD 233 | vender_code = 01 234 | flash_rom_type = 128KB 235 | 236 | # Pokemon Sapphire (I) 237 | game_name = POKEMON SAPP 238 | game_code = AXPI 239 | vender_code = 01 240 | flash_rom_type = 128KB 241 | 242 | # Pokemon Sapphire (S) 243 | game_name = POKEMON SAPP 244 | game_code = AXPS 245 | vender_code = 01 246 | flash_rom_type = 128KB 247 | 248 | # Pokemon Sapphire (F) 249 | game_name = POKEMON SAPP 250 | game_code = AXPF 251 | vender_code = 01 252 | flash_rom_type = 128KB 253 | 254 | # Pokemon Ruby (U) 255 | game_name = POKEMON RUBY 256 | game_code = AXVE 257 | vender_code = 01 258 | flash_rom_type = 128KB 259 | 260 | # Pokemon Ruby (J) 261 | game_name = POKEMON RUBY 262 | game_code = AXVJ 263 | vender_code = 01 264 | flash_rom_type = 128KB 265 | 266 | # Pokemon Ruby (G) 267 | game_name = POKEMON RUBY 268 | game_code = AXVD 269 | vender_code = 01 270 | flash_rom_type = 128KB 271 | 272 | # Pokemon Ruby (I) 273 | game_name = POKEMON RUBY 274 | game_code = AXVI 275 | vender_code = 01 276 | flash_rom_type = 128KB 277 | 278 | # Pokemon Ruby (S) 279 | game_name = POKEMON RUBY 280 | game_code = AXVS 281 | vender_code = 01 282 | flash_rom_type = 128KB 283 | 284 | # Pokemon Ruby (F) 285 | game_name = POKEMON RUBY 286 | game_code = AXVF 287 | vender_code = 01 288 | flash_rom_type = 128KB 289 | 290 | # V-Rally 3 (E) 291 | game_name = V-RALLY 3 292 | game_code = AVRP 293 | vender_code = 70 294 | idle_loop_eliminate_target = 080aa920 295 | 296 | # Mario Vs Donkey Kong (U) 297 | game_name = MARIOVSDK 298 | game_code = BM5E 299 | vender_code = 01 300 | idle_loop_eliminate_target = 08033eec 301 | 302 | # Pokemon: Sapphire (U) 303 | game_name = POKEMON SAPP 304 | game_code = AXPE 305 | vender_code = 01 306 | flash_rom_type = 128KB 307 | 308 | # Pokemon: Sapphire (G) 309 | game_name = POKEMON SAPP 310 | game_code = AXPD 311 | vender_code = 01 312 | flash_rom_type = 128KB 313 | 314 | # Pokemon: Fire Red (J) 315 | game_name = POKEMON FIRE 316 | game_code = BPRJ 317 | vender_code = 01 318 | idle_loop_eliminate_target = 080008b2 319 | # If you have the European version try this instead. 320 | #idle_loop_eliminate_target = 080008c6 321 | flash_rom_type = 128KB 322 | 323 | # Pokemon: Fire Red (E/U) 324 | game_name = POKEMON FIRE 325 | game_code = BPRE 326 | vender_code = 01 327 | idle_loop_eliminate_target = 080008c6 328 | flash_rom_type = 128KB 329 | 330 | # Pokemon: Fire Red (S) 331 | game_name = POKEMON FIRE 332 | game_code = BPRS 333 | vender_code = 01 334 | idle_loop_eliminate_target = 080008c6 335 | flash_rom_type = 128KB 336 | 337 | # Pokemon: Fire Red (G) 338 | game_name = POKEMON FIRE 339 | game_code = BPRD 340 | vender_code = 01 341 | idle_loop_eliminate_target = 080008c6 342 | flash_rom_type = 128KB 343 | 344 | # Pokemon: Fire Red (I) 345 | game_name = POKEMON FIRE 346 | game_code = BPRI 347 | vender_code = 01 348 | idle_loop_eliminate_target = 080008c6 349 | flash_rom_type = 128KB 350 | 351 | # Pokemon: Fire Red (F) 352 | game_name = POKEMON FIRE 353 | game_code = BPRE 354 | vender_code = 01 355 | idle_loop_eliminate_target = 080008c6 356 | flash_rom_type = 128KB 357 | 358 | # Pokemon: Leaf Green (E/U) 359 | # Hey, this one is the same as Fire Red, who'd have thought? :B 360 | game_name = POKEMON LEAF 361 | game_code = BPGE 362 | vender_code = 01 363 | idle_loop_eliminate_target = 080008b2 364 | flash_rom_type = 128KB 365 | 366 | # Pokemon: Leaf Green (S) 367 | game_name = POKEMON LEAF 368 | game_code = BPGS 369 | vender_code = 01 370 | idle_loop_eliminate_target = 080008b6 371 | flash_rom_type = 128KB 372 | 373 | # Pokemon: Leaf Green (G) 374 | game_name = POKEMON LEAF 375 | game_code = BPGD 376 | vender_code = 01 377 | idle_loop_eliminate_target = 080008b6 378 | flash_rom_type = 128KB 379 | 380 | # Pokemon: Leaf Green (I) 381 | game_name = POKEMON LEAF 382 | game_code = BPGI 383 | vender_code = 01 384 | idle_loop_eliminate_target = 080008b6 385 | flash_rom_type = 128KB 386 | 387 | # Pokemon: Leaf Green (F) 388 | game_name = POKEMON LEAF 389 | game_code = BPGF 390 | vender_code = 01 391 | idle_loop_eliminate_target = 080008b6 392 | flash_rom_type = 128KB 393 | 394 | # Pokemon: Fushigi no Dungeon Aka no Kyuujotai (J) 395 | game_name = POKE DUNGEON 396 | game_code = B24J 397 | vender_code = 01 398 | flash_rom_type = 128KB 399 | 400 | # Pokemon: Red Rescue Team (E/U) 401 | game_name = POKE DUNGEON 402 | game_code = B24E 403 | vender_code = 01 404 | flash_rom_type = 128KB 405 | 406 | # F-Zero: Climax (J) 407 | game_name = F-ZEROCLIMAX 408 | game_code = BFTJ 409 | vender_code = 01 410 | flash_rom_type = 128KB 411 | 412 | # Final Fantasy Tactics Advance (U) 413 | game_name = FFTA_USVER. 414 | game_code = AFXE 415 | vender_code = 01 416 | idle_loop_eliminate_target = 0800041e 417 | 418 | # Gradius Galaxies (U) 419 | # Badly coded game with several idle loops. This one works for level 420 | # one at least. 421 | game_name = GRADIUSGALAX 422 | game_code = AGAE 423 | vender_code = A4 424 | idle_loop_eliminate_target = 08013844 425 | 426 | # Rebelstar: Tactical Command (U) 427 | # Badly coded game with several idle loops. I don't think any are 428 | # even close to dominant, and it jumps around too much when things 429 | # matter.... 430 | game_name = REBELSTAR 431 | game_code = BRLE 432 | vender_code = AF 433 | idle_loop_eliminate_target = 0800041a 434 | 435 | # Golden Sun 436 | game_name = Golden_Sun_A 437 | game_code = AGSE 438 | vender_code = 01 439 | translation_gate_target = 03000820 440 | translation_gate_target = 030009ac 441 | 442 | # Golden Sun: The Lost Age (U) 443 | # Probably the most horrifically coded GBA game in existence. 444 | game_name = GOLDEN_SUN_B 445 | game_code = AGFE 446 | vender_code = 01 447 | idle_loop_eliminate_target = 08013542 448 | translation_gate_target = 030009ac 449 | translation_gate_target = 03007d70 450 | 451 | # Mario & Luigi: Superstar Saga (U) 452 | # Attempted fix. Works on x86 version, not on PSP one (but gets a 453 | # little further...) 454 | game_name = MARIO&LUIGIU 455 | game_code = A88E 456 | vender_code = 01 457 | #idle_loop_eliminate_target = 0801da90 458 | #0801db42 459 | 460 | # Mario Party Advance (U) 461 | game_name = MARIOPARTYUS 462 | game_code = B8ME 463 | vender_code = 01 464 | iwram_stack_optimize = no 465 | 466 | # Mario Golf: Advance Tour (U) 467 | game_name = MARIOGOLFGBA 468 | game_code = BMGE 469 | vender_code = 01 470 | iwram_stack_optimize = no 471 | idle_loop_eliminate_target = 08014e0a 472 | translation_gate_target = 03000d00 473 | translation_gate_target = 03000a30 474 | 475 | # Tales of Phantasia (U) 476 | game_name = PHANTASIA 477 | game_code = AN8E 478 | vender_code = 01 479 | iwram_stack_optimize = no 480 | 481 | # Advance Wars 2: Black Hole Rising (U) 482 | game_name = ADVANCEWARS2 483 | game_code = AW2E 484 | vender_code = 01 485 | idle_loop_eliminate_target = 08036e2a 486 | 487 | # Bomberman Tournament (U) 488 | game_name = BOMSTORYUSA 489 | game_code = ABSE 490 | vender_code = 52 491 | idle_loop_eliminate_target = 08000526 492 | 493 | # Broken Sword - The Shadow of the Templars (U) 494 | game_name = BROKENSWORD 495 | game_code = ABJE 496 | vender_code = 6L 497 | idle_loop_eliminate_target = 08000a26 498 | 499 | # Defender of The Crown (U) 500 | game_name = DOTC 501 | game_code = ADHE 502 | vender_code = 5N 503 | idle_loop_eliminate_target = 080007ec 504 | 505 | # Drill Dozer (U) 506 | game_name = DRILL DOZER 507 | game_code = V49E 508 | vender_code = 01 509 | idle_loop_eliminate_target = 080006c2 510 | 511 | # F-Zero - Maximum Velocity (U) 512 | game_name = F-ZERO ADVAN 513 | game_code = AFZE 514 | vender_code = 01 515 | idle_loop_eliminate_target = 08000c2e 516 | 517 | # Megaman Zero 2 (U) 518 | game_name = MEGAMANZERO2 519 | game_code = A62E 520 | vender_code = 08 521 | idle_loop_eliminate_target = 08000664 522 | 523 | # Megaman Zero 3 (U) 524 | game_name = MEGAMANZERO3 525 | game_code = BZ3E 526 | vender_code = 08 527 | idle_loop_eliminate_target = 08001a08 528 | 529 | # Megaman Zero 4 (U) 530 | game_name = MEGAMANZERO4 531 | game_code = B4ZE 532 | vender_code = 08 533 | idle_loop_eliminate_target = 0800090c 534 | 535 | # Metal Slug Advance (U) 536 | game_name = METAL SLUG 537 | game_code = BSME 538 | vender_code = B7 539 | idle_loop_eliminate_target = 08000298 540 | 541 | # Magical Quest 2 Starring Mickey & Minnie (U) 542 | game_name = M&M MAGICAL2 543 | game_code = AQME 544 | vender_code = 08 545 | idle_loop_eliminate_target = 0801d340 546 | 547 | # Magical Quest 3 Starring Mickey & Donald (U) 548 | game_name = M&D MAGICAL3 549 | game_code = BMQE 550 | vender_code = 08 551 | idle_loop_eliminate_target = 08016064 552 | 553 | # Pinball Challenge Deluxe (E) 554 | game_name = PINBALL CHAL 555 | game_code = APLP 556 | vender_code = 41 557 | idle_loop_eliminate_target = 080075a6 558 | 559 | # Prince of Persia - The Sands of Time (U) 560 | game_name = PRINCEPERSIA 561 | game_code = BPYE 562 | vender_code = 41 563 | idle_loop_eliminate_target = 0808ff3a 564 | 565 | # Rhythm Tengoku (J) 566 | game_name = RHYTHMTENGOK 567 | game_code = BRIJ 568 | vender_code = 01 569 | idle_loop_eliminate_target = 080013d4 570 | 571 | # River City Ransom EX (U) 572 | game_name = RIVERCRANSOM 573 | game_code = BDTE 574 | vender_code = EB 575 | idle_loop_eliminate_target = 0800065a 576 | 577 | # Super Puzzle Fighter II Turbo (U) 578 | game_name = PUZZLEFIGHT2 579 | game_code = AZ8E 580 | vender_code = 08 581 | idle_loop_eliminate_target = 08002b5e 582 | 583 | # Yu-Gi-Oh! - Dungeon Dice Monsters (U) 584 | game_name = YU-GI-OH DDM 585 | game_code = AYDE 586 | vender_code = A4 587 | idle_loop_eliminate_target = 0802cc6a 588 | 589 | # Yu-Gi-Oh! - The Eternal Duelist Soul (U) 590 | game_name = YU-GI-OH!EDS 591 | game_code = AY5E 592 | vender_code = A4 593 | idle_loop_eliminate_target = 08075d96 594 | 595 | # Yu-Gi-Oh! - The Sacred Cards (U) 596 | game_name = YUGIOH DM7 597 | game_code = AY7E 598 | vender_code = A4 599 | idle_loop_eliminate_target = 08003bd6 600 | 601 | # Yu-Gi-Oh! - World Championship Tournament 2004 (U) 602 | game_name = YWCT2004USA 603 | game_code = BYWE 604 | vender_code = A4 605 | idle_loop_eliminate_target = 080831da 606 | 607 | # Yu-Gi-Oh! - Worldwide Edition - Stairway to the Destined Duel (U) 608 | game_name = YUGIOHWWE 609 | game_code = AYWE 610 | vender_code = A4 611 | idle_loop_eliminate_target = 08089792 612 | 613 | # Wario Ware, Inc. Mega Microgames (U) 614 | game_name = WARIOWAREINC 615 | game_code = AZWE 616 | vender_code = 01 617 | idle_loop_eliminate_target = 08000f66 618 | 619 | # Tom Clancy's Splinter Cell (U) 620 | game_name = SPLINTERCELL 621 | game_code = AO4E 622 | vender_code = 41 623 | idle_loop_eliminate_target = 0807a0c4 624 | 625 | # Tom Clancy's Splinter Cell - Pandora Tomorrow (U) 626 | game_name = TOM CLANCY'S 627 | game_code = BSLE 628 | vender_code = 41 629 | idle_loop_eliminate_target = 0807785e 630 | 631 | # Final Fantasy IV Advance (U) 632 | game_name = FF4ADVANCE 633 | game_code = BZ4E 634 | vender_code = 01 635 | idle_loop_eliminate_target = 0800fabe 636 | # or try 00000430 637 | 638 | # Digimon Battle Spirit (U) 639 | game_name = DIGIMON BTSP 640 | game_code = A8SE 641 | vender_code = B2 642 | idle_loop_eliminate_target = 08011208 643 | 644 | # Digimon Battle Spirit 2 (U) 645 | game_name = DIGIMON BS2 646 | game_code = BDSE 647 | vender_code = B2 648 | idle_loop_eliminate_target = 08010eb0 649 | 650 | # Donald Duck Advance (U) 651 | game_name = DISNEY'S DON 652 | game_code = ADKE 653 | vender_code = 41 654 | idle_loop_eliminate_target = 08002f30 655 | 656 | # Final Fight One (U) 657 | game_name = FINAL FIGHT 658 | game_code = AFFE 659 | vender_code = 08 660 | idle_loop_eliminate_target = 0800b428 661 | 662 | # Megaman Battle Chip Challenge (U) 663 | game_name = BATTLECHIPGP 664 | game_code = A89E 665 | vender_code = 08 666 | idle_loop_eliminate_target = 08000544 667 | 668 | # Monster Force (U) 669 | game_name = MONSTERFORCE 670 | game_code = AM8E 671 | vender_code = 7D 672 | idle_loop_eliminate_target = 08000b00 673 | 674 | # Monster Rancher Advance (U) 675 | game_name = MONSRANCHERA 676 | game_code = AMFE 677 | vender_code = 9B 678 | idle_loop_eliminate_target = 0809f394 679 | 680 | # Monster Rancher Advance 2 (U) 681 | game_name = MONSTERRANC2 682 | game_code = A2QE 683 | vender_code = 9B 684 | idle_loop_eliminate_target = 081c7290 685 | 686 | # The Pinball of The Dead 687 | game_name = PINBALL DEAD 688 | game_code = APDE 689 | vender_code = 78 690 | idle_loop_eliminate_target = 08000300 691 | 692 | # Tringo (U) 693 | game_name = TRINGO 694 | game_code = BTJE 695 | vender_code = 4Z 696 | idle_loop_eliminate_target = 080009a4 697 | 698 | # Virtual Kasparov (U) 699 | game_name = VIRTKASPAROV 700 | game_code = AVKE 701 | vender_code = 60 702 | idle_loop_eliminate_target = 0800093a 703 | 704 | # Advance Wars 2 - Black Hole Rising (E) 705 | game_name = ADVANCEWARS2 706 | game_code = AW2P 707 | vender_code = 01 708 | idle_loop_eliminate_target = 080371be 709 | 710 | # Bookworm (U) 711 | game_name = BOOKWORM 712 | game_code = BKWE 713 | vender_code = 5G 714 | idle_loop_eliminate_target = 0800397c 715 | 716 | # 007 - Nightfire (U) 717 | game_name = NIGHTFIRE 718 | game_code = A7OE 719 | vender_code = 69 720 | idle_loop_eliminate_target = 080031d6 721 | -------------------------------------------------------------------------------- /dc/cd/gba_bios.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GPF/gPSPDC/9887759aee122eefff3cab6d7d9109ed34de60ee/dc/cd/gba_bios.bin -------------------------------------------------------------------------------- /dc/dc.sh: -------------------------------------------------------------------------------- 1 | sh-elf-objcopy -R .stack -O binary gdC.elf gdC.bin 2 | rm cd/1ST_READ.BIN 3 | $KOS_BASE/utils/scramble/scramble gdC.bin 1ST_READ.BIN 4 | cp 1ST_READ.BIN cd/ 5 | mkdcdisc -n gbapspDC -N -f cd/gba_bios.bin -d cd/gbaDC -e gdC.elf -o gbapspDC.cdi 6 | 7 | 8 | -------------------------------------------------------------------------------- /dc/gbapspDC.cdi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GPF/gPSPDC/9887759aee122eefff3cab6d7d9109ed34de60ee/dc/gbapspDC.cdi -------------------------------------------------------------------------------- /dc/gdC.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GPF/gPSPDC/9887759aee122eefff3cab6d7d9109ed34de60ee/dc/gdC.elf -------------------------------------------------------------------------------- /dc/sh4_emit.h: -------------------------------------------------------------------------------- 1 | #ifndef SH4_EMIT_H 2 | #define SH4_EMIT_H 3 | 4 | #include "common.h" 5 | #include "cpu.h" 6 | 7 | typedef u16* translation_ptr_t; 8 | extern translation_ptr_t translation_ptr; 9 | void translate_invalidate_dcache(void); 10 | void sh4_invalidate_icache_region(u32 addr, u32 size); 11 | 12 | typedef enum { 13 | sh4_reg_r0 = 0, // Temporary / Return value / Argument 0 (eax) 14 | sh4_reg_r1 = 1, // Temporary / Argument 1 (edx) 15 | sh4_reg_r2 = 2, // Temporary / Argument 2 (ecx) 16 | sh4_reg_r3 = 3, // Temporary / Argument 3 17 | sh4_reg_r4 = 4, // ARM R0 (static) 18 | sh4_reg_r5 = 5, // ARM R1 (static) 19 | sh4_reg_r6 = 6, // ARM R2 (static) 20 | sh4_reg_r7 = 7, // ARM R3 (static) 21 | sh4_reg_r8 = 8, // ARM R12 (static, often IP) 22 | sh4_reg_r9 = 9, // ARM R13 (SP, static) 23 | sh4_reg_r10 = 10, // ARM R14 (LR, static) 24 | sh4_reg_r11 = 11, // ARM R15 (PC, static) 25 | sh4_reg_r12 = 12, // Base register (emulator state pointer, reg[], ebx) 26 | sh4_reg_r13 = 13, // Cycle counter (edi) 27 | sh4_reg_r14 = 14, // Scratch / Temporary (esi) 28 | sh4_reg_r15 = 15 // Stack pointer (SP) 29 | } sh4_reg_number; 30 | 31 | #define REG_BASE sh4_reg_r12 32 | #define REG_CYCLES sh4_reg_r13 33 | #define REG_TEMP sh4_reg_r14 34 | #define REG_A0 sh4_reg_r0 35 | #define REG_A1 sh4_reg_r1 36 | #define REG_A2 sh4_reg_r2 37 | #define REG_A3 sh4_reg_r3 38 | #define REG_RV sh4_reg_r0 39 | #define REG_S0 sh4_reg_r14 40 | 41 | #define REG_R0 sh4_reg_r4 42 | #define REG_R1 sh4_reg_r5 43 | #define REG_R2 sh4_reg_r6 44 | #define REG_R3 sh4_reg_r7 45 | #define REG_R12 sh4_reg_r8 46 | #define REG_SP sh4_reg_r9 47 | #define REG_LR sh4_reg_r10 48 | #define REG_PC sh4_reg_r11 49 | 50 | extern u32 arm_to_sh4_reg[]; 51 | 52 | // SH-4 Instruction Emission Macros 53 | #define SH4_EMIT_BYTE(value) \ 54 | *(translation_ptr++) = (value) 55 | 56 | #define SH4_EMIT_DWORD(value) \ 57 | *(translation_ptr++) = (value & 0xFFFF); \ 58 | *(translation_ptr++) = ((value >> 16) & 0xFFFF) 59 | 60 | #define SH4_EMIT_ADD(rd, rn, rm) \ 61 | SH4_EMIT_BYTE(0x300C | ((rd & 0xF) << 8) | ((rn & 0xF) << 4) | (rm & 0xF)) 62 | 63 | #define SH4_EMIT_SUB(rd, rn, rm) \ 64 | SH4_EMIT_BYTE(0x3008 | ((rd & 0xF) << 8) | ((rn & 0xF) << 4) | (rm & 0xF)) 65 | 66 | #define SH4_EMIT_MOV(rd, rm) \ 67 | SH4_EMIT_BYTE(0x6003 | ((rd & 0xF) << 8) | ((rm & 0xF) << 4)) 68 | 69 | #define SH4_EMIT_MOVI(rd, imm) \ 70 | SH4_EMIT_BYTE(0xE000 | ((rd & 0xF) << 8) | (imm & 0xFF)) 71 | 72 | #define SH4_EMIT_ADDI(rd, rn, imm) \ 73 | SH4_EMIT_BYTE(0x7000 | ((rn & 0xF) << 8) | (imm & 0xFF)); \ 74 | if ((rd) != (rn)) SH4_EMIT_MOV(rd, rn) 75 | 76 | #define SH4_EMIT_LW(rd, rn, offset) \ 77 | SH4_EMIT_BYTE(0x6006 | ((rd & 0xF) << 8) | ((rn & 0xF) << 4) | ((offset >> 2) & 0xF)) 78 | 79 | #define SH4_EMIT_SW(rd, rn, offset) \ 80 | SH4_EMIT_BYTE(0x2006 | ((rd & 0xF) << 8) | ((rn & 0xF) << 4) | ((offset >> 2) & 0xF)) 81 | 82 | #define SH4_EMIT_CALL(target) \ 83 | SH4_EMIT_BYTE(0xD000 | (((u32)(target) >> 2) & 0xFFF)); \ 84 | SH4_EMIT_BYTE(0x0009) 85 | 86 | #define SH4_EMIT_JMP(target_reg) \ 87 | SH4_EMIT_BYTE(0x402B | ((target_reg & 0xF) << 8)); \ 88 | SH4_EMIT_BYTE(0x0009) 89 | 90 | #define SH4_EMIT_BRA(offset) \ 91 | SH4_EMIT_BYTE(0xA000 | ((offset >> 1) & 0xFFF)); \ 92 | SH4_EMIT_BYTE(0x0009) 93 | 94 | #define SH4_EMIT_BT(offset) \ 95 | SH4_EMIT_BYTE(0x8900 | ((offset >> 1) & 0xFF)); \ 96 | SH4_EMIT_BYTE(0x0009) 97 | 98 | #define SH4_EMIT_BF(offset) \ 99 | SH4_EMIT_BYTE(0x8B00 | ((offset >> 1) & 0xFF)); \ 100 | SH4_EMIT_BYTE(0x0009) 101 | 102 | #define SH4_EMIT_NOP() \ 103 | SH4_EMIT_BYTE(0x0009) 104 | 105 | // Types and Defines from x86_emit.h 106 | typedef enum { 107 | CONDITION_TRUE, 108 | CONDITION_FALSE, 109 | CONDITION_EQUAL, 110 | CONDITION_NOT_EQUAL 111 | } condition_check_type; 112 | 113 | extern u8 swi_hle_handle[256]; 114 | #define block_prologue_size 8 // No prologue for SH-4 yet, adjust if needed 115 | 116 | // Function Declarations 117 | u32 sh4_update_gba(u32 pc); 118 | void sh4_indirect_branch_arm(u32 address); 119 | void sh4_indirect_branch_thumb(u32 address); 120 | void sh4_indirect_branch_dual(u32 address); 121 | 122 | u32 function_cc sh4_execute_load_u8(u32 address); 123 | u32 function_cc sh4_execute_load_u16(u32 address); 124 | u32 function_cc sh4_execute_load_u32(u32 address); 125 | s32 function_cc sh4_execute_load_s8(u32 address); 126 | s32 function_cc sh4_execute_load_s16(u32 address); 127 | 128 | void function_cc sh4_execute_store_u8(u32 address, u32 value); 129 | void function_cc sh4_execute_store_u16(u32 address, u32 value); 130 | void function_cc sh4_execute_store_u32(u32 address, u32 value); 131 | 132 | u32 sh4_execute_aligned_load32(u32 address); 133 | void sh4_execute_aligned_store32(u32 address, u32 value); 134 | 135 | u32 function_cc execute_and(u32 rm, u32 rn); 136 | u32 function_cc execute_ands(u32 rm, u32 rn); 137 | u32 function_cc execute_eor(u32 rm, u32 rn); 138 | u32 function_cc execute_eors(u32 rm, u32 rn); 139 | u32 function_cc execute_sub(u32 rm, u32 rn); 140 | u32 function_cc execute_subs(u32 rm, u32 rn); 141 | u32 function_cc execute_rsb(u32 rm, u32 rn); 142 | u32 function_cc execute_rsbs(u32 rm, u32 rn); 143 | u32 function_cc execute_add(u32 rm, u32 rn); 144 | u32 function_cc execute_adds(u32 rm, u32 rn); 145 | u32 function_cc execute_adc(u32 rm, u32 rn); 146 | u32 function_cc execute_adcs(u32 rm, u32 rn); 147 | u32 function_cc execute_sbc(u32 rm, u32 rn); 148 | u32 function_cc execute_sbcs(u32 rm, u32 rn); 149 | u32 function_cc execute_rsc(u32 rm, u32 rn); 150 | u32 function_cc execute_rscs(u32 rm, u32 rn); 151 | u32 function_cc execute_orr(u32 rm, u32 rn); 152 | u32 function_cc execute_orrs(u32 rm, u32 rn); 153 | u32 function_cc execute_mov(u32 rm); 154 | u32 function_cc execute_movs(u32 rm); 155 | u32 function_cc execute_bic(u32 rm, u32 rn); 156 | u32 function_cc execute_bics(u32 rm, u32 rn); 157 | u32 function_cc execute_mvn(u32 rm); 158 | u32 function_cc execute_mvns(u32 rm); 159 | u32 function_cc execute_mul(u32 rm, u32 rs); 160 | u32 function_cc execute_muls(u32 rm, u32 rs); 161 | u32 function_cc execute_mul_long(u32 rm, u32 rs); 162 | u32 function_cc execute_tst(u32 rm, u32 rn); 163 | u32 function_cc execute_teq(u32 rm, u32 rn); 164 | u32 function_cc execute_cmp(u32 rm, u32 rn); 165 | u32 function_cc execute_cmn(u32 rm, u32 rn); 166 | u32 function_cc execute_lsl_imm(u32 value, u32 shift); 167 | u32 function_cc execute_lsr_imm(u32 value, u32 shift); 168 | u32 function_cc execute_asr_imm(u32 value, u32 shift); 169 | u32 function_cc execute_lsl_reg(u32 value, u32 shift); 170 | u32 function_cc execute_lsr_reg(u32 value, u32 shift); 171 | u32 function_cc execute_asr_reg(u32 value, u32 shift); 172 | u32 function_cc execute_ror_reg(u32 value, u32 shift); 173 | u32 function_cc execute_neg(u32 rm); 174 | 175 | u32 sh4_execute_read_cpsr(void); 176 | u32 sh4_execute_read_spsr(void); 177 | void sh4_execute_swi(u32 pc); 178 | u32 sh4_execute_spsr_restore(u32 address); 179 | void sh4_execute_store_cpsr(u32 new_cpsr, u32 store_mask); 180 | void sh4_execute_store_spsr(u32 new_spsr, u32 store_mask); 181 | 182 | u32 sh4_execute_lsl_flags_reg(u32 value, u32 shift); 183 | u32 sh4_execute_lsr_flags_reg(u32 value, u32 shift); 184 | u32 sh4_execute_asr_flags_reg(u32 value, u32 shift); 185 | u32 sh4_execute_ror_flags_reg(u32 value, u32 shift); 186 | 187 | u32 function_cc sh4_execute_arm_translate(u32 cycles); 188 | u32 function_cc sh4_execute_thumb_translate(u32 cycles); 189 | void sh4_step_debug(u32 pc); 190 | 191 | // Translation Macros 192 | #define SH4_EMIT_LOAD_REG(ireg, reg_index) \ 193 | SH4_EMIT_LW(ireg, REG_BASE, reg_index * 4) 194 | 195 | #define SH4_EMIT_STORE_REG(ireg, reg_index) \ 196 | SH4_EMIT_SW(ireg, REG_BASE, reg_index * 4) 197 | 198 | #define SH4_EMIT_OR(rd, rn, rm) \ 199 | SH4_EMIT_BYTE(0x300B | ((rd & 0xF) << 8) | ((rn & 0xF) << 4) | (rm & 0xF)) 200 | 201 | #define SH4_EMIT_LOAD_IMM(ireg, imm) \ 202 | if ((imm & 0xFF) == imm) { \ 203 | SH4_EMIT_MOVI(ireg, imm); \ 204 | } else { \ 205 | SH4_EMIT_MOVI(ireg, imm & 0xFF); \ 206 | SH4_EMIT_MOVI(REG_TEMP, (imm >> 8) & 0xFF); \ 207 | SH4_EMIT_ADDI(ireg, ireg, 8); \ 208 | SH4_EMIT_OR(ireg, ireg, REG_TEMP); \ 209 | if (imm > 0xFFFF) { \ 210 | SH4_EMIT_MOVI(REG_TEMP, (imm >> 16) & 0xFF); \ 211 | SH4_EMIT_ADDI(ireg, ireg, 8); \ 212 | SH4_EMIT_OR(ireg, ireg, REG_TEMP); \ 213 | SH4_EMIT_MOVI(REG_TEMP, (imm >> 24) & 0xFF); \ 214 | SH4_EMIT_ADDI(ireg, ireg, 8); \ 215 | SH4_EMIT_OR(ireg, ireg, REG_TEMP); \ 216 | } \ 217 | } 218 | 219 | #define SH4_EMIT_FUNCTION_CALL(func) \ 220 | SH4_EMIT_CALL(func) 221 | 222 | #define SH4_EMIT_JMP_OFFSET(offset) \ 223 | SH4_EMIT_BRA(SH4_RELATIVE_OFFSET(translation_ptr, offset)) 224 | 225 | #define SH4_RELATIVE_OFFSET(source, target) \ 226 | (((u32)(target) - ((u32)(source) + 2)) >> 1) 227 | 228 | // Translation Helpers 229 | #define generate_load_reg(ireg, reg_index) \ 230 | SH4_EMIT_LOAD_REG(ireg, reg_index) 231 | 232 | #define generate_store_reg(ireg, reg_index) \ 233 | SH4_EMIT_STORE_REG(ireg, reg_index) 234 | 235 | #define generate_load_imm(ireg, imm) \ 236 | SH4_EMIT_LOAD_IMM(ireg, imm) 237 | 238 | #define generate_function_call(func) \ 239 | SH4_EMIT_FUNCTION_CALL(func) 240 | 241 | #define generate_indirect_branch_arm() \ 242 | SH4_EMIT_FUNCTION_CALL(sh4_indirect_branch_arm) 243 | 244 | #define generate_indirect_branch_thumb() \ 245 | SH4_EMIT_FUNCTION_CALL(sh4_indirect_branch_thumb) 246 | 247 | #define generate_indirect_branch_dual() \ 248 | SH4_EMIT_FUNCTION_CALL(sh4_indirect_branch_dual) 249 | 250 | #define generate_branch() \ 251 | SH4_EMIT_JMP_OFFSET(block_exits[block_exit_position].branch_target); \ 252 | block_exit_position++ 253 | 254 | #define generate_block_prologue() \ 255 | /* No prologue for SH-4 yet, can add initialization here if needed */ 256 | 257 | #define arm_conditional_block_header() \ 258 | /* Placeholder for SH-4 conditional block header */ 259 | 260 | #define arm_bx() \ 261 | do { \ 262 | u32 rn = opcode & 0xF; \ 263 | SH4_EMIT_LOAD_REG(REG_A0, rn); \ 264 | SH4_EMIT_FUNCTION_CALL(sh4_indirect_branch_dual); \ 265 | } while (0) 266 | 267 | #define arm_b() \ 268 | do { \ 269 | s32 offset = ((s32)(opcode & 0xFFFFFF) << 8) >> 6; \ 270 | branch_target = block_end_pc + 4 + offset; \ 271 | block_exits[block_exit_position].branch_target = branch_target; \ 272 | block_exits[block_exit_position].branch_source = translation_ptr; \ 273 | SH4_EMIT_BRA(0); \ 274 | block_exit_position++; \ 275 | } while (0) 276 | 277 | #define arm_bl() \ 278 | do { \ 279 | s32 offset = ((s32)(opcode & 0xFFFFFF) << 8) >> 6; \ 280 | branch_target = block_end_pc + 4 + offset; \ 281 | SH4_EMIT_MOVI(REG_LR, block_end_pc + 4); /* Set link register */ \ 282 | block_exits[block_exit_position].branch_target = branch_target; \ 283 | block_exits[block_exit_position].branch_source = translation_ptr; \ 284 | SH4_EMIT_BRA(0); \ 285 | block_exit_position++; \ 286 | } while (0) 287 | 288 | #define arm_swi() \ 289 | do { \ 290 | SH4_EMIT_FUNCTION_CALL(sh4_execute_swi); \ 291 | } while (0) 292 | 293 | #define generate_branch_patch_conditional(backpatch_address, target) \ 294 | SH4_EMIT_BRANCH_PATCH_CONDITIONAL(backpatch_address, target) 295 | 296 | #define generate_branch_patch_unconditional(backpatch_address, target) \ 297 | SH4_EMIT_BRANCH_PATCH_UNCONDITIONAL(backpatch_address, target) 298 | 299 | #define generate_update_pc_reg() \ 300 | SH4_EMIT_FUNCTION_CALL(sh4_update_gba) 301 | 302 | #define generate_cycle_update() \ 303 | SH4_EMIT_CYCLE_UPDATE() 304 | 305 | #define generate_translation_gate(type) \ 306 | SH4_EMIT_FUNCTION_CALL(sh4_execute_##type##_translate) 307 | 308 | #define SH4_EMIT_CYCLE_UPDATE() \ 309 | SH4_EMIT_SUB(REG_CYCLES, REG_CYCLES, cycle_count); \ 310 | cycle_count = 0 311 | 312 | #define SH4_EMIT_BRANCH_PATCH_CONDITIONAL(dest, offset) \ 313 | *((u16 *)(dest)) = (SH4_RELATIVE_OFFSET(dest, offset) & 0xFF) 314 | 315 | #define SH4_EMIT_BRANCH_PATCH_UNCONDITIONAL(dest, offset) \ 316 | *((u16 *)(dest)) = (SH4_RELATIVE_OFFSET(dest, offset) & 0xFFF) 317 | 318 | // Expanded Translation Macros from x86_emit.h 319 | #define arm_data_proc(name, type, flags_op) \ 320 | do { \ 321 | u32 rn = (opcode >> 16) & 0xF; \ 322 | u32 rd = (opcode >> 12) & 0xF; \ 323 | u32 rm = opcode & 0xF; \ 324 | SH4_EMIT_LOAD_REG(REG_A0, rm); \ 325 | SH4_EMIT_LOAD_REG(REG_A1, rn); \ 326 | SH4_EMIT_FUNCTION_CALL(execute_##name); \ 327 | SH4_EMIT_STORE_REG(REG_RV, rd); \ 328 | } while (0) 329 | 330 | #define arm_data_proc_unary(name, type, flags_op) \ 331 | do { \ 332 | u32 rd = (opcode >> 12) & 0xF; \ 333 | u32 rm = opcode & 0xF; \ 334 | SH4_EMIT_LOAD_REG(REG_A0, rm); \ 335 | SH4_EMIT_FUNCTION_CALL(execute_##name); \ 336 | SH4_EMIT_STORE_REG(REG_RV, rd); \ 337 | } while (0) 338 | 339 | #define arm_data_proc_test(name, type) \ 340 | do { \ 341 | u32 rn = (opcode >> 16) & 0xF; \ 342 | u32 rm = opcode & 0xF; \ 343 | SH4_EMIT_LOAD_REG(REG_A0, rm); \ 344 | SH4_EMIT_LOAD_REG(REG_A1, rn); \ 345 | SH4_EMIT_FUNCTION_CALL(execute_##name); \ 346 | } while (0) 347 | 348 | #define arm_multiply(add_op, flags) \ 349 | do { \ 350 | u32 rm = opcode & 0xF; \ 351 | u32 rs = (opcode >> 8) & 0xF; \ 352 | u32 rd = (opcode >> 16) & 0xF; \ 353 | SH4_EMIT_LOAD_REG(REG_A0, rm); \ 354 | SH4_EMIT_LOAD_REG(REG_A1, rs); \ 355 | SH4_EMIT_FUNCTION_CALL(execute_mul); \ 356 | SH4_EMIT_STORE_REG(REG_RV, rd); \ 357 | } while (0) 358 | 359 | #define arm_multiply_long(name, add_op, flags) \ 360 | do { \ 361 | u32 rm = opcode & 0xF; \ 362 | u32 rs = (opcode >> 8) & 0xF; \ 363 | u32 rdlo = (opcode >> 12) & 0xF; \ 364 | u32 rdhi = (opcode >> 16) & 0xF; \ 365 | SH4_EMIT_LOAD_REG(REG_A0, rm); \ 366 | SH4_EMIT_LOAD_REG(REG_A1, rs); \ 367 | SH4_EMIT_FUNCTION_CALL(execute_mul_long); \ 368 | SH4_EMIT_STORE_REG(REG_RV, rdlo); \ 369 | SH4_EMIT_STORE_REG(REG_A1, rdhi); \ 370 | } while (0) 371 | 372 | #define arm_access_memory(access_type, direction, adjust_op, mem_type, offset_type) \ 373 | do { \ 374 | u32 rn = (opcode >> 16) & 0xF; \ 375 | u32 rd = (opcode >> 12) & 0xF; \ 376 | SH4_EMIT_LOAD_REG(REG_A0, rn); \ 377 | SH4_EMIT_FUNCTION_CALL(sh4_execute_##access_type##_##mem_type); \ 378 | SH4_EMIT_STORE_REG(REG_RV, rd); \ 379 | } while (0) 380 | 381 | #define arm_swap(type) \ 382 | do { \ 383 | u32 rn = (opcode >> 16) & 0xF; \ 384 | u32 rd = (opcode >> 12) & 0xF; \ 385 | u32 rm = opcode & 0xF; \ 386 | SH4_EMIT_LOAD_REG(REG_A0, rn); \ 387 | SH4_EMIT_FUNCTION_CALL(sh4_execute_load_##type); \ 388 | SH4_EMIT_MOV(REG_S0, REG_RV); \ 389 | SH4_EMIT_LOAD_REG(REG_A0, rn); \ 390 | SH4_EMIT_LOAD_REG(REG_A1, rm); \ 391 | SH4_EMIT_FUNCTION_CALL(sh4_execute_store_##type); \ 392 | SH4_EMIT_STORE_REG(REG_S0, rd); \ 393 | } while (0) 394 | 395 | #define arm_psr(op_type, transfer_type, psr_reg) \ 396 | do { \ 397 | u32 rm = opcode & 0xF; \ 398 | SH4_EMIT_FUNCTION_CALL(sh4_execute_##transfer_type##_##psr_reg); \ 399 | SH4_EMIT_STORE_REG(REG_RV, rm); \ 400 | } while (0) 401 | 402 | #define thumb_data_proc(type, name, rn_type, _rd, _rs, _rn) \ 403 | do { \ 404 | u32 rd = opcode & 0x7; \ 405 | u32 rs = (opcode >> 3) & 0x7; \ 406 | u32 rn = (opcode >> 6) & 0x7; \ 407 | SH4_EMIT_LOAD_REG(REG_A0, rs); \ 408 | SH4_EMIT_LOAD_REG(REG_A1, rn); \ 409 | SH4_EMIT_FUNCTION_CALL(execute_##name); \ 410 | SH4_EMIT_STORE_REG(REG_RV, rd); \ 411 | } while (0) 412 | 413 | #define thumb_data_proc_unary(type, name, rn_type, _rd, _rn) \ 414 | do { \ 415 | u32 rd = opcode & 0x7; \ 416 | u32 rn = (opcode >> 3) & 0x7; \ 417 | SH4_EMIT_LOAD_REG(REG_A0, rn); \ 418 | SH4_EMIT_FUNCTION_CALL(execute_##name); \ 419 | SH4_EMIT_STORE_REG(REG_RV, rd); \ 420 | } while (0) 421 | 422 | #define thumb_data_proc_test(type, name, rn_type, _rs, _rn) \ 423 | do { \ 424 | u32 rs = (opcode >> 3) & 0x7; \ 425 | u32 rn = (opcode >> 6) & 0x7; \ 426 | SH4_EMIT_LOAD_REG(REG_A0, rs); \ 427 | SH4_EMIT_LOAD_REG(REG_A1, rn); \ 428 | SH4_EMIT_FUNCTION_CALL(execute_##name); \ 429 | } while (0) 430 | 431 | #define thumb_shift(decode_type, op_type, value_type) \ 432 | do { \ 433 | u32 rd = opcode & 0x7; \ 434 | u32 rs = (opcode >> 3) & 0x7; \ 435 | SH4_EMIT_LOAD_REG(REG_A0, rs); \ 436 | SH4_EMIT_FUNCTION_CALL(execute_##op_type##_##value_type); \ 437 | SH4_EMIT_STORE_REG(REG_RV, rd); \ 438 | } while (0) 439 | 440 | #define thumb_access_memory(access_type, op_type, reg_rd, reg_rb, reg_ro, address_type, offset, mem_type) \ 441 | do { \ 442 | u32 rd = (reg_rd); \ 443 | u32 rb = (reg_rb); \ 444 | SH4_EMIT_LOAD_REG(REG_A0, rb); \ 445 | SH4_EMIT_FUNCTION_CALL(sh4_execute_##access_type##_##mem_type); \ 446 | SH4_EMIT_STORE_REG(REG_RV, rd); \ 447 | } while (0) 448 | 449 | #define arm_block_memory(access_type, pre_op, post_op, wb) \ 450 | do { \ 451 | u32 rn = (opcode >> 16) & 0xF; \ 452 | SH4_EMIT_LOAD_REG(REG_A0, rn); \ 453 | SH4_EMIT_FUNCTION_CALL(sh4_execute_##access_type##_u32); \ 454 | SH4_EMIT_STORE_REG(REG_RV, rn); \ 455 | } while (0) 456 | 457 | #define thumb_block_memory(access_type, pre_op, post_op, base_reg) \ 458 | do { \ 459 | u32 rb = (base_reg); \ 460 | SH4_EMIT_LOAD_REG(REG_A0, rb); \ 461 | SH4_EMIT_FUNCTION_CALL(sh4_execute_##access_type##_u32); \ 462 | SH4_EMIT_STORE_REG(REG_RV, rb); \ 463 | } while (0) 464 | 465 | #define thumb_data_proc_hi(name) \ 466 | do { \ 467 | u32 rd = ((opcode >> 4) & 0x08) | (opcode & 0x7); \ 468 | u32 rs = (opcode >> 3) & 0xF; \ 469 | SH4_EMIT_LOAD_REG(REG_A0, rs); \ 470 | SH4_EMIT_FUNCTION_CALL(execute_##name); \ 471 | SH4_EMIT_STORE_REG(REG_RV, rd); \ 472 | } while (0) 473 | 474 | #define thumb_data_proc_test_hi(name) \ 475 | do { \ 476 | u32 rs = (opcode >> 3) & 0x7; \ 477 | u32 rn = (opcode >> 6) & 0x7; \ 478 | SH4_EMIT_LOAD_REG(REG_A0, rs); \ 479 | SH4_EMIT_LOAD_REG(REG_A1, rn); \ 480 | SH4_EMIT_FUNCTION_CALL(execute_##name); \ 481 | } while (0) 482 | 483 | #define thumb_conditional_branch(condition) \ 484 | SH4_EMIT_BT(0) // Placeholder, needs proper offset logic 485 | 486 | #define thumb_load_pc(reg_num) \ 487 | do { \ 488 | u32 imm = (opcode & 0xFF) << 2; \ 489 | SH4_EMIT_LOAD_IMM(REG_A0, block_end_pc + imm); \ 490 | SH4_EMIT_STORE_REG(REG_RV, reg_num); \ 491 | } while (0) 492 | 493 | #define thumb_load_sp(reg_num) \ 494 | do { \ 495 | u32 imm = (opcode & 0xFF) << 2; \ 496 | SH4_EMIT_LOAD_REG(REG_A0, REG_SP); \ 497 | SH4_EMIT_ADDI(REG_A0, REG_A0, imm); \ 498 | SH4_EMIT_FUNCTION_CALL(sh4_execute_load_u32); \ 499 | SH4_EMIT_STORE_REG(REG_RV, reg_num); \ 500 | } while (0) 501 | 502 | #define thumb_adjust_sp(imm_val) \ 503 | do { \ 504 | SH4_EMIT_LOAD_REG(REG_A0, REG_SP); \ 505 | SH4_EMIT_ADDI(REG_A0, REG_A0, imm_val); \ 506 | SH4_EMIT_STORE_REG(REG_A0, REG_SP); \ 507 | } while (0) 508 | 509 | #define thumb_b() \ 510 | do { \ 511 | u32 offset = (opcode & 0x7FF) << 1; \ 512 | if (offset & 0x800) offset |= 0xFFFFF000; \ 513 | branch_target = block_end_pc + 2 + offset; \ 514 | block_exits[block_exit_position].branch_target = branch_target; \ 515 | block_exits[block_exit_position].branch_source = translation_ptr; \ 516 | SH4_EMIT_BRA(0); \ 517 | block_exit_position++; \ 518 | } while (0) 519 | 520 | #define thumb_bl() \ 521 | do { \ 522 | u32 offset = ((last_opcode & 0x7FF) << 12) | ((opcode & 0x7FF) << 1); \ 523 | if (offset & 0x400000) offset |= 0xFF800000; \ 524 | branch_target = block_end_pc + 2 + offset; \ 525 | block_exits[block_exit_position].branch_target = branch_target; \ 526 | block_exits[block_exit_position].branch_source = translation_ptr; \ 527 | SH4_EMIT_BRA(0); \ 528 | block_exit_position++; \ 529 | } while (0) 530 | 531 | #define thumb_blh() \ 532 | do { \ 533 | SH4_EMIT_FUNCTION_CALL(sh4_indirect_branch_thumb); \ 534 | } while (0) 535 | 536 | #define thumb_swi() \ 537 | do { \ 538 | SH4_EMIT_FUNCTION_CALL(sh4_execute_swi); \ 539 | } while (0) 540 | 541 | #define thumb_bx() \ 542 | do { \ 543 | u32 rn = (opcode >> 3) & 0xF; \ 544 | SH4_EMIT_LOAD_REG(REG_A0, rn); \ 545 | SH4_EMIT_FUNCTION_CALL(sh4_indirect_branch_dual); \ 546 | } while (0) 547 | 548 | // Block Translation Variables 549 | #define SH4_GENERATE_BLOCK_EXTRA_VARS() \ 550 | u32 stored_pc = pc; 551 | 552 | #define generate_block_extra_vars_arm SH4_GENERATE_BLOCK_EXTRA_VARS 553 | #define generate_block_extra_vars_thumb SH4_GENERATE_BLOCK_EXTRA_VARS 554 | 555 | #endif // SH4_EMIT_H -------------------------------------------------------------------------------- /dc/sh4_stub.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "sh4_emit.h" 3 | 4 | // External declarations 5 | extern u32 reg[]; 6 | extern u32 spsr[]; 7 | extern u8* memory_map_read[]; 8 | extern u8* memory_map_write[]; 9 | extern u32 update_gba(); 10 | extern u8* block_lookup_address_arm(u32 pc); 11 | extern u8* block_lookup_address_thumb(u32 pc); 12 | extern u8* block_lookup_address_dual(u32 pc); 13 | extern u8 read_memory8(u32 address); 14 | extern u32 read_memory16(u32 address); 15 | extern u32 read_memory32(u32 address); 16 | extern cpu_alert_type write_memory8(u32 address, u8 value); 17 | extern cpu_alert_type write_memory16(u32 address, u16 value); 18 | extern cpu_alert_type write_memory32(u32 address, u32 value); 19 | extern void flush_translation_cache_ram(); 20 | extern u32 step_debug(u32 pc, u32 cycles); 21 | 22 | // Utility functions 23 | static inline void collapse_flags() { 24 | reg[REG_CPSR] = (reg[REG_N_FLAG] << 31) | 25 | (reg[REG_Z_FLAG] << 30) | 26 | (reg[REG_C_FLAG] << 29) | 27 | (reg[REG_V_FLAG ] << 28) | 28 | (reg[REG_CPSR] & 0xFF); 29 | } 30 | 31 | static inline void extract_flags() { 32 | reg[REG_N_FLAG] = (reg[REG_CPSR] >> 31) & 1; 33 | reg[REG_Z_FLAG] = (reg[REG_CPSR] >> 30) & 1; 34 | reg[REG_C_FLAG] = (reg[REG_CPSR] >> 29) & 1; 35 | reg[REG_V_FLAG] = (reg[REG_CPSR] >> 28) & 1; 36 | } 37 | 38 | u32 sh4_update_gba(u32 pc) { 39 | u32 cycles; 40 | reg[REG_PC] = pc; 41 | collapse_flags(); 42 | cycles = update_gba(); 43 | if (reg[CHANGED_PC_STATUS] != 0) { 44 | u32 new_pc = reg[REG_PC]; 45 | reg[CHANGED_PC_STATUS] = 0; 46 | if (reg[REG_CPSR] & 0x20) { 47 | return (u32)block_lookup_address_thumb(new_pc); 48 | } else { 49 | return (u32)block_lookup_address_arm(new_pc); 50 | } 51 | } 52 | return cycles; 53 | } 54 | 55 | void sh4_indirect_branch_arm(u32 address) { 56 | u8* target = block_lookup_address_arm(address); 57 | ((void (*)())target)(); 58 | } 59 | 60 | void sh4_indirect_branch_thumb(u32 address) { 61 | u8* target = block_lookup_address_thumb(address); 62 | ((void (*)())target)(); 63 | } 64 | 65 | void sh4_indirect_branch_dual(u32 address) { 66 | u8* target = block_lookup_address_dual(address); 67 | ((void (*)())target)(); 68 | } 69 | 70 | void function_cc sh4_execute_store_u8(u32 address, u32 value) { 71 | reg[REG_PC] = address; 72 | if (!(address & 0xF0000000)) { 73 | u32 page = address >> 15; 74 | u8* map = memory_map_write[page]; 75 | if (map) { 76 | u32 offset = address & 0x7FFF; 77 | map[offset] = (u8)value; 78 | if (map[offset - 32768] != 0) { 79 | flush_translation_cache_ram(); 80 | goto lookup_pc; 81 | } 82 | return; 83 | } 84 | } 85 | cpu_alert_type result = write_memory8(address, (u8)value); 86 | if (result != CPU_ALERT_NONE) { 87 | collapse_flags(); 88 | if (result == CPU_ALERT_SMC) { 89 | flush_translation_cache_ram(); 90 | goto lookup_pc; 91 | } 92 | do { 93 | result = update_gba(); 94 | } while (reg[CPU_HALT_STATE] != 0); 95 | goto lookup_pc; 96 | } 97 | return; 98 | 99 | lookup_pc: 100 | reg[CHANGED_PC_STATUS] = 0; 101 | address = reg[REG_PC]; 102 | if (reg[REG_CPSR] & 0x20) { 103 | ((void (*)())block_lookup_address_thumb(address))(); 104 | } else { 105 | ((void (*)())block_lookup_address_arm(address))(); 106 | } 107 | } 108 | 109 | void function_cc sh4_execute_store_u16(u32 address, u32 value) { 110 | address &= ~0x1; 111 | reg[REG_PC] = address; 112 | if (!(address & 0xF0000000)) { 113 | u32 page = address >> 15; 114 | u8* map = memory_map_write[page]; 115 | if (map) { 116 | u32 offset = address & 0x7FFF; 117 | *(u16*)(map + offset) = (u16)value; 118 | if (*(u16*)(map + offset - 32768) != 0) { 119 | flush_translation_cache_ram(); 120 | goto lookup_pc; 121 | } 122 | return; 123 | } 124 | } 125 | cpu_alert_type result = write_memory16(address, (u16)value); 126 | if (result != CPU_ALERT_NONE) { 127 | collapse_flags(); 128 | if (result == CPU_ALERT_SMC) { 129 | flush_translation_cache_ram(); 130 | goto lookup_pc; 131 | } 132 | do { 133 | result = update_gba(); 134 | } while (reg[CPU_HALT_STATE] != 0); 135 | goto lookup_pc; 136 | } 137 | return; 138 | 139 | lookup_pc: 140 | reg[CHANGED_PC_STATUS] = 0; 141 | address = reg[REG_PC]; 142 | if (reg[REG_CPSR] & 0x20) { 143 | ((void (*)())block_lookup_address_thumb(address))(); 144 | } else { 145 | ((void (*)())block_lookup_address_arm(address))(); 146 | } 147 | } 148 | 149 | void function_cc sh4_execute_store_u32(u32 address, u32 value) { 150 | address &= ~0x3; 151 | reg[REG_PC] = address; 152 | if (!(address & 0xF0000000)) { 153 | u32 page = address >> 15; 154 | u8* map = memory_map_write[page]; 155 | if (map) { 156 | u32 offset = address & 0x7FFF; 157 | *(u32*)(map + offset) = value; 158 | if (*(u32*)(map + offset - 32768) != 0) { 159 | flush_translation_cache_ram(); 160 | goto lookup_pc; 161 | } 162 | return; 163 | } 164 | } 165 | cpu_alert_type result = write_memory32(address, value); 166 | if (result != CPU_ALERT_NONE) { 167 | collapse_flags(); 168 | if (result == CPU_ALERT_SMC) { 169 | flush_translation_cache_ram(); 170 | goto lookup_pc; 171 | } 172 | do { 173 | result = update_gba(); 174 | } while (reg[CPU_HALT_STATE] != 0); 175 | goto lookup_pc; 176 | } 177 | return; 178 | 179 | lookup_pc: 180 | reg[CHANGED_PC_STATUS] = 0; 181 | address = reg[REG_PC]; 182 | if (reg[REG_CPSR] & 0x20) { 183 | ((void (*)())block_lookup_address_thumb(address))(); 184 | } else { 185 | ((void (*)())block_lookup_address_arm(address))(); 186 | } 187 | } 188 | 189 | void translate_invalidate_dcache() { 190 | icache_flush_range((uint32)ram_translation_cache, 191 | (uint32)(ram_translation_ptr - ram_translation_cache) + 0x100); 192 | } 193 | 194 | void sh4_invalidate_icache_region(u32 addr, u32 size) { 195 | icache_flush_range(addr, size); 196 | } 197 | 198 | u32 function_cc sh4_execute_arm_translate(u32 cycles) { 199 | extract_flags(); 200 | u32 pc = reg[REG_PC]; 201 | u8* target = block_lookup_address_arm(pc); 202 | if (target != NULL) { 203 | printf("Dynarec ARM: Executing block at %p for PC %08x\n", target, pc); 204 | ((void (*)())target)(); 205 | } else { 206 | printf("Dynarec ARM: Fallback at PC %08x\n", pc); 207 | // Add fallback interpreter call here if it exists 208 | } 209 | return cycles; 210 | } 211 | u32 function_cc sh4_execute_thumb_translate(u32 cycles) { 212 | extract_flags(); 213 | u32 pc = reg[REG_PC]; 214 | u8* target = block_lookup_address_thumb(pc); 215 | if (target != NULL) { 216 | printf("Dynarec Thumb: Executing block at %p for PC %08x\n", target, pc); 217 | ((void (*)())target)(); 218 | } else { 219 | printf("Dynarec Thumb: Fallback at PC %08x\n", pc); 220 | // Add fallback interpreter call here if it exists 221 | } 222 | return cycles; 223 | } 224 | 225 | 226 | void sh4_step_debug(u32 pc) { 227 | collapse_flags(); 228 | step_debug(pc, reg[REG_CYCLES]); 229 | } -------------------------------------------------------------------------------- /gp2x/Makefile: -------------------------------------------------------------------------------- 1 | # gpSP makefile 2 | # Gilead Kutnick - Exophase 3 | # GP2X port(ion) - Z 4 | 5 | # Global definitions 6 | 7 | CCPREFIX = arm-linux- 8 | CC = ${CCPREFIX}gcc 9 | STRIP = ${CCPREFIX}strip 10 | AS = ${CCPREFIX}as 11 | 12 | PREFIX = /c/gp2x/devkitGP2X/sysroot/usr 13 | OBJS = main.o cpu.o memory.o video.o input.o sound.o \ 14 | arm_stub.o gp2x.o gui.o zip.o 15 | ASMOBJS = arm_stub.S 16 | BIN = gpsp.gpe 17 | 18 | # Platform specific definitions 19 | 20 | VPATH += .. 21 | CFLAGS += -O3 -DGP2X_BUILD 22 | # NOTE: -funroll-loops will slow down compiling considerably 23 | # -fno-common was required to get games to start 24 | CFLAGS += -funroll-loops -fstrength-reduce -fstrict-aliasing -fexpensive-optimizations -falign-functions -fweb -frename-registers -fomit-frame-pointer -ffast-math -fno-builtin -fno-common -finline -finline-functions 25 | #CFLAGS += -fsigned-char -funroll-loops -fstrength-reduce -fstrict-aliasing -fexpensive-optimizations -falign-functions -fweb -frename-registers -fomit-frame-pointer -ffast-math -fno-builtin -fno-common -finline -finline-functions 26 | CXXFLAGS = ${CFLAGS} -fno-exceptions -fno-rtti 27 | ASFLAGS = ${CFLAGS} 28 | INCLUDES = -I${PREFIX}/include -I${PREFIX}/include/SDL 29 | LIBS = -L${PREFIX}/lib -lSDL -lpthread -lz -static 30 | 31 | # Compilation: 32 | 33 | .SUFFIXES: .c 34 | 35 | %.o: %.c 36 | ${CC} ${CFLAGS} ${INCLUDES} -c -o $@ $< 37 | 38 | all: ${OBJS} 39 | ${CC} ${OBJS} ${LIBS} -o ${BIN} 40 | ${STRIP} ${BIN} 41 | 42 | clean: 43 | rm -f *.o ${BIN} 44 | 45 | -------------------------------------------------------------------------------- /gp2x/arm_emit.h: -------------------------------------------------------------------------------- 1 | /* gameplaySP 2 | * 3 | * Copyright (C) 2006 Exophase 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License as 7 | * published by the Free Software Foundation; either version 2 of 8 | * the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #ifndef ARM_EMIT_H 21 | #define ARM_EMIT_H 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /gp2x/arm_stub.c: -------------------------------------------------------------------------------- 1 | /* gameplaySP 2 | * 3 | * Copyright (C) 2006 Exophase 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License as 7 | * published by the Free Software Foundation; either version 2 of 8 | * the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #include "../common.h" 21 | 22 | // Temporary replacement of cpu_threaded.c declarations shoved in here for the time being 23 | u8 rom_translation_cache[ROM_TRANSLATION_CACHE_SIZE]; 24 | u8 *rom_translation_ptr = rom_translation_cache; 25 | 26 | u8 ram_translation_cache[RAM_TRANSLATION_CACHE_SIZE]; 27 | u8 *ram_translation_ptr = ram_translation_cache; 28 | u32 iwram_code_min = 0xFFFFFFFF; 29 | u32 iwram_code_max = 0xFFFFFFFF; 30 | u32 ewram_code_min = 0xFFFFFFFF; 31 | u32 ewram_code_max = 0xFFFFFFFF; 32 | 33 | u8 bios_translation_cache[BIOS_TRANSLATION_CACHE_SIZE]; 34 | u8 *bios_translation_ptr = bios_translation_cache; 35 | 36 | u32 *rom_branch_hash[ROM_BRANCH_HASH_SIZE]; 37 | 38 | // Default 39 | u32 idle_loop_target_pc = 0xFFFFFFFF; 40 | u32 translation_gate_target_pc[MAX_TRANSLATION_GATES]; 41 | u32 translation_gate_targets = 0; 42 | u32 iwram_stack_optimize = 1; 43 | 44 | void dump_translation_cache() {} 45 | void flush_translation_cache_bios() {} 46 | void flush_translation_cache_rom() {} 47 | void flush_translation_cache_ram() {} 48 | 49 | // Temporary replacement of stub declarations for use with interpreter to make things easier 50 | u8 *memory_map_read[8 * 1024]; 51 | u32 reg[64]; 52 | u8 *memory_map_write[8 * 1024]; 53 | -------------------------------------------------------------------------------- /gp2x/cpuctrl.gpl.txt: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc. 5 | 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Library General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License 307 | along with this program; if not, write to the Free Software 308 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 309 | 310 | 311 | Also add information on how to contact you by electronic and paper mail. 312 | 313 | If the program is interactive, make it output a short notice like this 314 | when it starts in an interactive mode: 315 | 316 | Gnomovision version 69, Copyright (C) year name of author 317 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 318 | This is free software, and you are welcome to redistribute it 319 | under certain conditions; type `show c' for details. 320 | 321 | The hypothetical commands `show w' and `show c' should show the appropriate 322 | parts of the General Public License. Of course, the commands you use may 323 | be called something other than `show w' and `show c'; they could even be 324 | mouse-clicks or menu items--whatever suits your program. 325 | 326 | You should also get your employer (if you work as a programmer) or your 327 | school, if any, to sign a "copyright disclaimer" for the program, if 328 | necessary. Here is a sample; alter the names: 329 | 330 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 331 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 332 | 333 | , 1 April 1989 334 | Ty Coon, President of Vice 335 | 336 | This General Public License does not permit incorporating your program into 337 | proprietary programs. If your program is a subroutine library, you may 338 | consider it more useful to permit linking proprietary applications with the 339 | library. If this is what you want to do, use the GNU Library General 340 | Public License instead of this License. 341 | -------------------------------------------------------------------------------- /gp2x/gp2x.c: -------------------------------------------------------------------------------- 1 | /* Parts used from cpuctrl */ 2 | /* cpuctrl for GP2X 3 | Copyright (C) 2005 Hermes/PS2Reality 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | 19 | */ 20 | 21 | 22 | #include 23 | #include "gp2x.h" 24 | #include "../common.h" 25 | 26 | u32 gp2x_dev = 0; 27 | volatile u16 *gp2x_memregs; 28 | volatile u32 *gp2x_memregl; 29 | 30 | /* system registers */ 31 | static struct 32 | { 33 | unsigned short SYSCLKENREG,SYSCSETREG,FPLLVSETREG,DUALINT920,DUALINT940,DUALCTRL940; 34 | } 35 | system_reg; 36 | 37 | static unsigned short dispclockdiv; 38 | 39 | static volatile unsigned short *MEM_REG; 40 | 41 | #define SYS_CLK_FREQ 7372800 42 | 43 | enum { GP2X_UP=0x1, GP2X_LEFT=0x4, GP2X_DOWN=0x10, GP2X_RIGHT=0x40, 44 | GP2X_START=(1<<8), GP2X_SELECT=1<<9, GP2X_L=(1<<10), GP2X_R=(1<<11), 45 | GP2X_A=1<<12, GP2X_B=1<<13, GP2X_X=1<<14, GP2X_Y=1<<15, 46 | GP2X_VOL_UP=1<<23, GP2X_VOL_DOWN=(1<<22), GP2X_PUSH=1<<27 }; 47 | 48 | void cpuctrl_init(void) 49 | { 50 | MEM_REG=&gp2x_memregs[0]; 51 | system_reg.SYSCSETREG=MEM_REG[0x91c>>1]; 52 | system_reg.FPLLVSETREG=MEM_REG[0x912>>1]; 53 | system_reg.SYSCLKENREG=MEM_REG[0x904>>1]; 54 | system_reg.DUALINT920=MEM_REG[0x3B40>>1]; 55 | system_reg.DUALINT940=MEM_REG[0x3B42>>1]; 56 | system_reg.DUALCTRL940=MEM_REG[0x3B48>>1]; 57 | dispclockdiv=MEM_REG[0x924>>1]; 58 | } 59 | 60 | 61 | void cpuctrl_deinit(void) 62 | { 63 | MEM_REG[0x91c>>1]=system_reg.SYSCSETREG; 64 | MEM_REG[0x910>>1]=system_reg.FPLLVSETREG; 65 | MEM_REG[0x3B40>>1]=system_reg.DUALINT920; 66 | MEM_REG[0x3B42>>1]=system_reg.DUALINT940; 67 | MEM_REG[0x3B48>>1]=system_reg.DUALCTRL940; 68 | MEM_REG[0x904>>1]=system_reg.SYSCLKENREG; 69 | MEM_REG[0x924>>1]=dispclockdiv; 70 | } 71 | 72 | 73 | void set_display_clock_div(unsigned div) 74 | { 75 | div=((div & 63) | 64)<<8; 76 | MEM_REG[0x924>>1]=(MEM_REG[0x924>>1] & ~(255<<8)) | div; 77 | } 78 | 79 | 80 | void set_FCLK(unsigned MHZ) 81 | { 82 | unsigned v; 83 | unsigned mdiv,pdiv=3,scale=0; 84 | MHZ*=1000000; 85 | mdiv=(MHZ*pdiv)/SYS_CLK_FREQ; 86 | mdiv=((mdiv-8)<<8) & 0xff00; 87 | pdiv=((pdiv-2)<<2) & 0xfc; 88 | scale&=3; 89 | v=mdiv | pdiv | scale; 90 | MEM_REG[0x910>>1]=v; 91 | } 92 | 93 | unsigned short get_920_Div() 94 | { 95 | return (MEM_REG[0x91c>>1] & 0x7); 96 | } 97 | 98 | void set_920_Div(unsigned short div) 99 | { 100 | unsigned short v; 101 | v = MEM_REG[0x91c>>1] & (~0x3); 102 | MEM_REG[0x91c>>1] = (div & 0x7) | v; 103 | } 104 | 105 | 106 | void set_DCLK_Div( unsigned short div ) 107 | { 108 | unsigned short v; 109 | v = (unsigned short)( MEM_REG[0x91c>>1] & (~(0x7 << 6)) ); 110 | MEM_REG[0x91c>>1] = ((div & 0x7) << 6) | v; 111 | } 112 | 113 | void set_940_Div(unsigned short div) 114 | { 115 | unsigned short v; 116 | v = (unsigned short)( MEM_REG[0x91c>>1] & (~(0x7 << 3))); 117 | MEM_REG[0x91c>>1] = ((div & 0x7) << 3) | v; 118 | } 119 | 120 | void Disable_940(void) 121 | { 122 | MEM_REG[0x3B42>>1]; 123 | MEM_REG[0x3B42>>1]=0; 124 | MEM_REG[0x3B46>>1]=0xffff; 125 | MEM_REG[0x3B48>>1]|= (1 << 7); 126 | MEM_REG[0x904>>1]&=0xfffe; 127 | } 128 | 129 | void gp2x_video_wait_vsync(void) 130 | { 131 | MEM_REG[0x2846>>1]=(MEM_REG[0x2846>>1] | 0x20) & ~2; 132 | while(!(MEM_REG[0x2846>>1] & 2)); 133 | } 134 | 135 | 136 | void gp2x_overclock(void) 137 | { 138 | int frag = 0x80000|7; 139 | unsigned lfreq[25]={60,66,80,100,120,133,150,166,200,210,220,240,250,266,270,275,280,285,290,295,300,305,310,315,320}; 140 | int cur_freq = 8; 141 | char ocstr[256]; 142 | 143 | print_string("USE THE L AND R TRIGGERS TO SELECT CPU SPEED", 0xFFFF, 0x0000, 0, 0); 144 | print_string("PRESS START TO SET CLOCKSPEED AND CONTINUE", 0xFFFF, 0x0000, 0, 10); 145 | flip_screen(); 146 | 147 | cpuctrl_init(); 148 | 149 | for(;;) 150 | { 151 | unsigned long keys = gp2x_joystick_read(); 152 | sprintf(ocstr, "CPU WILL BE SET TO: %3u ", lfreq[cur_freq]); 153 | print_string(ocstr, 0xFFFF, 0x0000, 0, 20); 154 | flip_screen(); 155 | 156 | if( keys & GP2X_L ) 157 | { 158 | if( cur_freq > 0 ) cur_freq--; 159 | } 160 | if( keys & GP2X_R ) 161 | { 162 | if( cur_freq < 24 ) cur_freq++; 163 | } 164 | if( keys & GP2X_START ) 165 | { 166 | int m; 167 | m=get_920_Div(); 168 | set_FCLK(lfreq[cur_freq]); 169 | set_920_Div(m); 170 | set_940_Div(m); 171 | set_DCLK_Div(m); 172 | break; 173 | } 174 | 175 | delay_us(100000); 176 | } 177 | } 178 | 179 | void gp2x_quit(void) 180 | { 181 | cpuctrl_deinit(); 182 | munmap((void *)gp2x_memregl, 0x10000); 183 | close(gp2x_dev); 184 | chdir("/usr/gp2x"); 185 | execl("gp2xmenu","gp2xmenu",NULL); 186 | } -------------------------------------------------------------------------------- /gp2x/gp2x.h: -------------------------------------------------------------------------------- 1 | #ifndef __GPSP_GP2X_H__ 2 | #define __GPSP_GP2X_H__ 3 | 4 | extern u32 gp2x_dev; 5 | extern volatile u16 *gp2x_memregs; 6 | extern volatile u32 *gp2x_memregl; 7 | 8 | extern void gp2x_quit(void); 9 | extern void cpuctrl_init(void); /* call this at first */ 10 | extern void save_system_regs(void); /* save some registers */ 11 | extern void cpuctrl_deinit(void); 12 | extern void set_display_clock_div(unsigned div); 13 | extern void set_FCLK(unsigned MHZ); /* adjust the clock frequency (in Mhz units) */ 14 | extern void set_920_Div(unsigned short div); /* 0 to 7 divider (freq=FCLK/(1+div)) */ 15 | extern void set_DCLK_Div(unsigned short div); /* 0 to 7 divider (freq=FCLK/(1+div)) */ 16 | extern void Disable_940(void); /* 940t down */ 17 | extern void gp2x_video_wait_vsync(void); 18 | extern unsigned short get_920_Div(); 19 | extern void set_940_Div(unsigned short div); 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /gui.h: -------------------------------------------------------------------------------- 1 | /* gameplaySP 2 | * 3 | * Copyright (C) 2006 Exophase 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License as 7 | * published by the Free Software Foundation; either version 2 of 8 | * the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #ifndef GUI_H 21 | #define GUI_H 22 | 23 | #define GPSP_CONFIG_FILENAME "gpsp.cfg" 24 | 25 | s32 load_file(u8 **wildcards, u8 *result); 26 | u32 adjust_frameskip(u32 button_id); 27 | s32 load_game_config_file(); 28 | s32 load_config_file(); 29 | s32 save_game_config_file(); 30 | s32 save_config_file(); 31 | u32 menu(u16 *original_screen); 32 | 33 | extern u32 savestate_slot; 34 | 35 | #endif 36 | 37 | -------------------------------------------------------------------------------- /input.c: -------------------------------------------------------------------------------- 1 | /* gameplaySP 2 | * 3 | * Copyright (C) 2006 Exophase 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License as 7 | * published by the Free Software Foundation; either version 2 of 8 | * the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #include "common.h" 21 | #include "input.h" 22 | // Special thanks to psp298 for the analog->dpad code! 23 | 24 | void trigger_key(u32 key) 25 | { 26 | u32 p1_cnt = io_registers[REG_P1CNT]; 27 | u32 p1; 28 | 29 | if((p1_cnt >> 14) & 0x01) 30 | { 31 | u32 key_intersection = (p1_cnt & key) & 0x3FF; 32 | 33 | if(p1_cnt >> 15) 34 | { 35 | if(key_intersection == (p1_cnt & 0x3FF)) 36 | raise_interrupt(IRQ_KEYPAD); 37 | } 38 | else 39 | { 40 | if(key_intersection) 41 | raise_interrupt(IRQ_KEYPAD); 42 | } 43 | } 44 | } 45 | 46 | u32 key = 0; 47 | 48 | u32 gamepad_config_map[16] = 49 | { 50 | BUTTON_ID_MENU, 51 | BUTTON_ID_A, 52 | BUTTON_ID_B, 53 | BUTTON_ID_START, 54 | BUTTON_ID_L, 55 | BUTTON_ID_R, 56 | BUTTON_ID_DOWN, 57 | BUTTON_ID_LEFT, 58 | BUTTON_ID_UP, 59 | BUTTON_ID_RIGHT, 60 | BUTTON_ID_SELECT, 61 | BUTTON_ID_START, 62 | BUTTON_ID_UP, 63 | BUTTON_ID_DOWN, 64 | BUTTON_ID_LEFT, 65 | BUTTON_ID_RIGHT 66 | }; 67 | 68 | u32 global_enable_analog = 1; 69 | u32 analog_sensitivity_level = 4; 70 | 71 | #ifdef PSP_BUILD 72 | 73 | #define PSP_ALL_BUTTON_MASK 0xFFFF 74 | 75 | u32 last_buttons = 0; 76 | u64 button_repeat_timestamp; 77 | 78 | typedef enum 79 | { 80 | BUTTON_NOT_HELD, 81 | BUTTON_HELD_INITIAL, 82 | BUTTON_HELD_REPEAT 83 | } button_repeat_state_type; 84 | 85 | button_repeat_state_type button_repeat_state = BUTTON_NOT_HELD; 86 | u32 button_repeat = 0; 87 | gui_action_type cursor_repeat = CURSOR_NONE; 88 | 89 | #define BUTTON_REPEAT_START 200000 90 | #define BUTTON_REPEAT_CONTINUE 50000 91 | 92 | gui_action_type get_gui_input() 93 | { 94 | SceCtrlData ctrl_data; 95 | gui_action_type new_button = CURSOR_NONE; 96 | u32 new_buttons; 97 | 98 | delay_us(25000); 99 | 100 | sceCtrlPeekBufferPositive(&ctrl_data, 1); 101 | ctrl_data.Buttons &= PSP_ALL_BUTTON_MASK; 102 | new_buttons = (last_buttons ^ ctrl_data.Buttons) & ctrl_data.Buttons; 103 | last_buttons = ctrl_data.Buttons; 104 | 105 | if(new_buttons & PSP_CTRL_LEFT) 106 | new_button = CURSOR_LEFT; 107 | 108 | if(new_buttons & PSP_CTRL_RIGHT) 109 | new_button = CURSOR_RIGHT; 110 | 111 | if(new_buttons & PSP_CTRL_UP) 112 | new_button = CURSOR_UP; 113 | 114 | if(new_buttons & PSP_CTRL_DOWN) 115 | new_button = CURSOR_DOWN; 116 | 117 | if(new_buttons & PSP_CTRL_START) 118 | new_button = CURSOR_SELECT; 119 | 120 | if(new_buttons & PSP_CTRL_CIRCLE) 121 | new_button = CURSOR_SELECT; 122 | 123 | if(new_buttons & PSP_CTRL_CROSS) 124 | new_button = CURSOR_EXIT; 125 | 126 | if(new_buttons & PSP_CTRL_SQUARE) 127 | new_button = CURSOR_BACK; 128 | 129 | if(new_button != CURSOR_NONE) 130 | { 131 | get_ticks_us(&button_repeat_timestamp); 132 | button_repeat_state = BUTTON_HELD_INITIAL; 133 | button_repeat = new_buttons; 134 | cursor_repeat = new_button; 135 | } 136 | else 137 | { 138 | if(ctrl_data.Buttons & button_repeat) 139 | { 140 | u64 new_ticks; 141 | get_ticks_us(&new_ticks); 142 | 143 | if(button_repeat_state == BUTTON_HELD_INITIAL) 144 | { 145 | if((new_ticks - button_repeat_timestamp) > 146 | BUTTON_REPEAT_START) 147 | { 148 | new_button = cursor_repeat; 149 | button_repeat_timestamp = new_ticks; 150 | button_repeat_state = BUTTON_HELD_REPEAT; 151 | } 152 | } 153 | 154 | if(button_repeat_state == BUTTON_HELD_REPEAT) 155 | { 156 | if((new_ticks - button_repeat_timestamp) > 157 | BUTTON_REPEAT_CONTINUE) 158 | { 159 | new_button = cursor_repeat; 160 | button_repeat_timestamp = new_ticks; 161 | } 162 | } 163 | } 164 | } 165 | 166 | return new_button; 167 | } 168 | 169 | #define PSP_CTRL_ANALOG_UP (1 << 28) 170 | #define PSP_CTRL_ANALOG_DOWN (1 << 29) 171 | #define PSP_CTRL_ANALOG_LEFT (1 << 30) 172 | #define PSP_CTRL_ANALOG_RIGHT (1 << 31) 173 | 174 | u32 button_psp_mask_to_config[] = 175 | { 176 | PSP_CTRL_TRIANGLE, 177 | PSP_CTRL_CIRCLE, 178 | PSP_CTRL_CROSS, 179 | PSP_CTRL_SQUARE, 180 | PSP_CTRL_LTRIGGER, 181 | PSP_CTRL_RTRIGGER, 182 | PSP_CTRL_DOWN, 183 | PSP_CTRL_LEFT, 184 | PSP_CTRL_UP, 185 | PSP_CTRL_RIGHT, 186 | PSP_CTRL_SELECT, 187 | PSP_CTRL_START, 188 | PSP_CTRL_ANALOG_UP, 189 | PSP_CTRL_ANALOG_DOWN, 190 | PSP_CTRL_ANALOG_LEFT, 191 | PSP_CTRL_ANALOG_RIGHT 192 | }; 193 | 194 | u32 button_id_to_gba_mask[] = 195 | { 196 | BUTTON_UP, 197 | BUTTON_DOWN, 198 | BUTTON_LEFT, 199 | BUTTON_RIGHT, 200 | BUTTON_A, 201 | BUTTON_B, 202 | BUTTON_L, 203 | BUTTON_R, 204 | BUTTON_START, 205 | BUTTON_SELECT, 206 | BUTTON_NONE, 207 | BUTTON_NONE, 208 | BUTTON_NONE, 209 | BUTTON_NONE 210 | }; 211 | 212 | gui_action_type get_gui_input_fs_hold(u32 button_id) 213 | { 214 | gui_action_type new_button = get_gui_input(); 215 | if((last_buttons & button_psp_mask_to_config[button_id]) == 0) 216 | return CURSOR_BACK; 217 | 218 | return new_button; 219 | } 220 | 221 | u32 rapidfire_flag = 1; 222 | 223 | u32 update_input() 224 | { 225 | SceCtrlData ctrl_data; 226 | u32 buttons; 227 | u32 non_repeat_buttons; 228 | u32 button_id; 229 | u32 i; 230 | u32 new_key = 0; 231 | u32 analog_sensitivity = 92 - (analog_sensitivity_level * 4); 232 | u32 inv_analog_sensitivity = 256 - analog_sensitivity; 233 | 234 | sceCtrlPeekBufferPositive(&ctrl_data, 1); 235 | 236 | buttons = ctrl_data.Buttons; 237 | 238 | if(global_enable_analog) 239 | { 240 | if(ctrl_data.Lx < analog_sensitivity) 241 | buttons |= PSP_CTRL_ANALOG_LEFT; 242 | 243 | if(ctrl_data.Lx > inv_analog_sensitivity) 244 | buttons |= PSP_CTRL_ANALOG_RIGHT; 245 | 246 | if(ctrl_data.Ly < analog_sensitivity) 247 | buttons |= PSP_CTRL_ANALOG_UP; 248 | 249 | if(ctrl_data.Ly > inv_analog_sensitivity) 250 | buttons |= PSP_CTRL_ANALOG_DOWN; 251 | } 252 | 253 | non_repeat_buttons = (last_buttons ^ buttons) & buttons; 254 | last_buttons = buttons; 255 | 256 | for(i = 0; i < 16; i++) 257 | { 258 | if(non_repeat_buttons & button_psp_mask_to_config[i]) 259 | button_id = gamepad_config_map[i]; 260 | 261 | switch(button_id) 262 | { 263 | case BUTTON_ID_MENU: 264 | { 265 | u16 *screen_copy = copy_screen(); 266 | u32 ret_val = menu(screen_copy); 267 | free(screen_copy); 268 | 269 | return ret_val; 270 | } 271 | 272 | case BUTTON_ID_LOADSTATE: 273 | { 274 | u8 current_savestate_filename[512]; 275 | get_savestate_filename_noshot(savestate_slot, 276 | current_savestate_filename); 277 | load_state(current_savestate_filename); 278 | return 1; 279 | } 280 | 281 | case BUTTON_ID_SAVESTATE: 282 | { 283 | u8 current_savestate_filename[512]; 284 | u16 *current_screen = copy_screen(); 285 | get_savestate_filename_noshot(savestate_slot, 286 | current_savestate_filename); 287 | save_state(current_savestate_filename, current_screen); 288 | free(current_screen); 289 | return 0; 290 | } 291 | 292 | case BUTTON_ID_FASTFORWARD: 293 | synchronize_flag ^= 1; 294 | return 0; 295 | } 296 | 297 | if(buttons & button_psp_mask_to_config[i]) 298 | { 299 | button_id = gamepad_config_map[i]; 300 | if(button_id < BUTTON_ID_MENU) 301 | { 302 | new_key |= button_id_to_gba_mask[button_id]; 303 | } 304 | else 305 | 306 | if((button_id >= BUTTON_ID_RAPIDFIRE_A) && 307 | (button_id <= BUTTON_ID_RAPIDFIRE_L)) 308 | { 309 | rapidfire_flag ^= 1; 310 | if(rapidfire_flag) 311 | { 312 | new_key |= button_id_to_gba_mask[button_id - 313 | BUTTON_ID_RAPIDFIRE_A + BUTTON_ID_A]; 314 | } 315 | else 316 | { 317 | new_key &= ~button_id_to_gba_mask[button_id - 318 | BUTTON_ID_RAPIDFIRE_A + BUTTON_ID_A]; 319 | } 320 | } 321 | } 322 | } 323 | 324 | if((new_key | key) != key) 325 | trigger_key(new_key); 326 | 327 | key = new_key; 328 | 329 | io_registers[REG_P1] = (~key) & 0x3FF; 330 | 331 | return 0; 332 | } 333 | 334 | void init_input() 335 | { 336 | sceCtrlSetSamplingCycle(0); 337 | sceCtrlSetSamplingMode(PSP_CTRL_MODE_ANALOG); 338 | } 339 | 340 | #else 341 | 342 | u32 key_map(SDLKey key_sym) 343 | { 344 | switch(key_sym) 345 | { 346 | case SDLK_LSHIFT: 347 | return BUTTON_L; 348 | 349 | case SDLK_x: 350 | return BUTTON_R; 351 | 352 | case SDLK_DOWN: 353 | return BUTTON_DOWN; 354 | 355 | case SDLK_UP: 356 | return BUTTON_UP; 357 | 358 | case SDLK_LEFT: 359 | return BUTTON_LEFT; 360 | 361 | case SDLK_RIGHT: 362 | return BUTTON_RIGHT; 363 | 364 | case SDLK_RETURN: 365 | return BUTTON_START; 366 | 367 | case SDLK_RSHIFT: 368 | return BUTTON_SELECT; 369 | 370 | case SDLK_LCTRL: 371 | return BUTTON_B; 372 | 373 | case SDLK_LALT: 374 | return BUTTON_A; 375 | 376 | default: 377 | return BUTTON_NONE; 378 | } 379 | } 380 | 381 | u32 joy_map(u32 button) 382 | { 383 | switch(button) 384 | { 385 | case 4: 386 | return BUTTON_L; 387 | 388 | case 5: 389 | return BUTTON_R; 390 | 391 | case 9: 392 | return BUTTON_START; 393 | 394 | case 8: 395 | return BUTTON_SELECT; 396 | 397 | case 0: 398 | return BUTTON_B; 399 | 400 | case 1: 401 | return BUTTON_A; 402 | 403 | default: 404 | return BUTTON_NONE; 405 | } 406 | } 407 | 408 | 409 | u32 joy_hat_map(u32 value) 410 | { 411 | u32 result = BUTTON_NONE; 412 | 413 | if(value & SDL_HAT_UP) 414 | result |= BUTTON_UP; 415 | 416 | if(value & SDL_HAT_RIGHT) 417 | result |= BUTTON_RIGHT; 418 | 419 | if(value & SDL_HAT_DOWN) 420 | result |= BUTTON_DOWN; 421 | 422 | if(value & SDL_HAT_LEFT) 423 | result |= BUTTON_LEFT; 424 | 425 | return result; 426 | } 427 | 428 | gui_action_type get_gui_input() 429 | { 430 | SDL_Event event; 431 | gui_action_type gui_action = CURSOR_NONE; 432 | 433 | delay_us(30000); 434 | 435 | while(SDL_PollEvent(&event)) 436 | { 437 | switch(event.type) 438 | { 439 | case SDL_QUIT: 440 | quit(); 441 | 442 | case SDL_KEYDOWN: 443 | { 444 | switch(event.key.keysym.sym) 445 | { 446 | case SDLK_ESCAPE: 447 | gui_action = CURSOR_EXIT; 448 | break; 449 | 450 | case SDLK_DOWN: 451 | gui_action = CURSOR_DOWN; 452 | break; 453 | 454 | case SDLK_UP: 455 | gui_action = CURSOR_UP; 456 | break; 457 | 458 | case SDLK_LEFT: 459 | gui_action = CURSOR_LEFT; 460 | break; 461 | 462 | case SDLK_RIGHT: 463 | gui_action = CURSOR_RIGHT; 464 | break; 465 | 466 | case SDLK_RETURN: 467 | gui_action = CURSOR_SELECT; 468 | break; 469 | 470 | case SDLK_BACKSPACE: 471 | gui_action = CURSOR_BACK; 472 | break; 473 | } 474 | break; 475 | } 476 | case SDL_JOYHATMOTION: 477 | { 478 | if(event.jhat.value & SDL_HAT_UP) 479 | gui_action = CURSOR_UP; 480 | 481 | if(event.jhat.value & SDL_HAT_RIGHT) 482 | gui_action = CURSOR_RIGHT; 483 | 484 | if(event.jhat.value & SDL_HAT_DOWN) 485 | gui_action = CURSOR_DOWN; 486 | 487 | if(event.jhat.value & SDL_HAT_LEFT) 488 | gui_action = CURSOR_LEFT; 489 | break; 490 | } 491 | case SDL_JOYBUTTONDOWN: 492 | { 493 | if(event.jbutton.button ==0) 494 | gui_action = CURSOR_SELECT; 495 | if(event.jbutton.button ==1) 496 | gui_action = CURSOR_BACK; 497 | if(event.jbutton.button ==4) 498 | gui_action = CURSOR_EXIT; 499 | break; 500 | } 501 | } 502 | } 503 | 504 | return gui_action; 505 | } 506 | 507 | // FIXME: Not implemented properly for x86 version. 508 | 509 | gui_action_type get_gui_input_fs_hold(u32 button_id) 510 | { 511 | return get_gui_input(); 512 | } 513 | int axlast=0; 514 | u32 update_input() 515 | { 516 | SDL_Event event; 517 | 518 | while(SDL_PollEvent(&event)) 519 | { 520 | switch(event.type) 521 | { 522 | case SDL_QUIT: 523 | quit(); 524 | 525 | case SDL_KEYDOWN: 526 | { 527 | if(event.key.keysym.sym == SDLK_ESCAPE) 528 | { 529 | quit(); 530 | } 531 | 532 | if(event.key.keysym.sym == SDLK_BACKSPACE) 533 | { 534 | u16 *screen_copy = copy_screen(); 535 | u32 ret_val = menu(screen_copy); 536 | free(screen_copy); 537 | 538 | return ret_val; 539 | } 540 | else 541 | 542 | if(event.key.keysym.sym == SDLK_F1) 543 | { 544 | current_debug_state = STEP; 545 | } 546 | else 547 | 548 | if(event.key.keysym.sym == SDLK_F2) 549 | { 550 | FILE *fp = fopen("palette_ram.bin", "wb"); 551 | printf("writing palette RAM\n"); 552 | fwrite(palette_ram, 1024, 1, fp); 553 | fclose(fp); 554 | printf("writing palette VRAM\n"); 555 | fp = fopen("vram.bin", "wb"); 556 | fwrite(vram, 1024 * 96, 1, fp); 557 | fclose(fp); 558 | printf("writing palette OAM RAM\n"); 559 | fp = fopen("oam_ram.bin", "wb"); 560 | fwrite(oam_ram, 1024, 1, fp); 561 | fclose(fp); 562 | printf("writing palette I/O registers\n"); 563 | fp = fopen("io_registers.bin", "wb"); 564 | fwrite(io_registers, 1024, 1, fp); 565 | fclose(fp); 566 | } 567 | else 568 | 569 | if(event.key.keysym.sym == SDLK_F3) 570 | { 571 | dump_translation_cache(); 572 | } 573 | else 574 | 575 | if(event.key.keysym.sym == SDLK_F5) 576 | { 577 | u8 current_savestate_filename[512]; 578 | u16 *current_screen = copy_screen(); 579 | get_savestate_filename_noshot(savestate_slot, 580 | current_savestate_filename); 581 | save_state(current_savestate_filename, current_screen); 582 | free(current_screen); 583 | } 584 | else 585 | 586 | if(event.key.keysym.sym == SDLK_F7) 587 | { 588 | u8 current_savestate_filename[512]; 589 | get_savestate_filename_noshot(savestate_slot, 590 | current_savestate_filename); 591 | load_state(current_savestate_filename); 592 | current_debug_state = STEP; 593 | return 1; 594 | } 595 | else 596 | 597 | if(event.key.keysym.sym == SDLK_BACKQUOTE) 598 | { 599 | synchronize_flag ^= 1; 600 | } 601 | else 602 | { 603 | key |= key_map(event.key.keysym.sym); 604 | trigger_key(key); 605 | } 606 | 607 | break; 608 | } 609 | 610 | case SDL_KEYUP: 611 | { 612 | key &= ~(key_map(event.key.keysym.sym)); 613 | break; 614 | } 615 | case SDL_JOYAXISMOTION: 616 | { 617 | if(axlast){ 618 | if (axlast==2) 619 | key &= ~(BUTTON_L); 620 | if(axlast==3) 621 | key &= ~(BUTTON_R); 622 | 623 | if (axlast>0){ 624 | trigger_key(key); 625 | axlast=0; 626 | } 627 | } 628 | else{ 629 | if (event.jaxis.axis ==2) 630 | {key |= BUTTON_L;axlast=2;trigger_key(key);} 631 | if (event.jaxis.axis ==3) 632 | {key |= BUTTON_R;axlast=3;trigger_key(key);} 633 | } 634 | 635 | break; 636 | } 637 | 638 | case SDL_JOYHATMOTION: 639 | { 640 | key = (key & 0xFF0F) | joy_hat_map(event.jhat.value); 641 | trigger_key(key); 642 | break; 643 | } 644 | 645 | case SDL_JOYBUTTONDOWN: 646 | { 647 | key |= joy_map(event.jbutton.button); 648 | trigger_key(key); 649 | break; 650 | } 651 | 652 | case SDL_JOYBUTTONUP: 653 | { 654 | key &= ~(joy_map(event.jbutton.button)); 655 | break; 656 | } 657 | } 658 | } 659 | 660 | io_registers[REG_P1] = (~key) & 0x3FF; 661 | 662 | return 0; 663 | } 664 | 665 | void init_input() 666 | { 667 | u32 joystick_count = SDL_NumJoysticks(); 668 | 669 | if(joystick_count > 0) 670 | { 671 | SDL_JoystickOpen(0); 672 | SDL_JoystickEventState(SDL_ENABLE); 673 | } 674 | } 675 | 676 | #endif 677 | 678 | #define input_savestate_builder(type) \ 679 | void input_##type##_savestate(file_tag_type savestate_file) \ 680 | { \ 681 | file_##type##_variable(savestate_file, key); \ 682 | } \ 683 | 684 | input_savestate_builder(read); 685 | input_savestate_builder(write_mem); 686 | 687 | -------------------------------------------------------------------------------- /input.h: -------------------------------------------------------------------------------- 1 | /* gameplaySP 2 | * 3 | * Copyright (C) 2006 Exophase 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License as 7 | * published by the Free Software Foundation; either version 2 of 8 | * the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #ifndef INPUT_H 21 | #define INPUT_H 22 | 23 | void get_savestate_filename_noshot(u32 slot, u8 *name_buffer); 24 | typedef enum 25 | { 26 | BUTTON_L = 0x200, 27 | BUTTON_R = 0x100, 28 | BUTTON_DOWN = 0x80, 29 | BUTTON_UP = 0x40, 30 | BUTTON_LEFT = 0x20, 31 | BUTTON_RIGHT = 0x10, 32 | BUTTON_START = 0x08, 33 | BUTTON_SELECT = 0x04, 34 | BUTTON_B = 0x02, 35 | BUTTON_A = 0x01, 36 | BUTTON_NONE = 0x00 37 | } input_buttons_type; 38 | 39 | typedef enum 40 | { 41 | BUTTON_ID_UP, 42 | BUTTON_ID_DOWN, 43 | BUTTON_ID_LEFT, 44 | BUTTON_ID_RIGHT, 45 | BUTTON_ID_A, 46 | BUTTON_ID_B, 47 | BUTTON_ID_L, 48 | BUTTON_ID_R, 49 | BUTTON_ID_START, 50 | BUTTON_ID_SELECT, 51 | BUTTON_ID_MENU, 52 | BUTTON_ID_FASTFORWARD, 53 | BUTTON_ID_LOADSTATE, 54 | BUTTON_ID_SAVESTATE, 55 | BUTTON_ID_RAPIDFIRE_A, 56 | BUTTON_ID_RAPIDFIRE_B, 57 | BUTTON_ID_RAPIDFIRE_L, 58 | BUTTON_ID_RAPIDFIRE_R, 59 | BUTTON_ID_NONE 60 | } input_buttons_id_type; 61 | 62 | typedef enum 63 | { 64 | CURSOR_UP, 65 | CURSOR_DOWN, 66 | CURSOR_LEFT, 67 | CURSOR_RIGHT, 68 | CURSOR_SELECT, 69 | CURSOR_BACK, 70 | CURSOR_EXIT, 71 | CURSOR_NONE 72 | } gui_action_type; 73 | 74 | void init_input(); 75 | u32 update_input(); 76 | gui_action_type get_gui_input(); 77 | gui_action_type get_gui_input_fs_hold(u32 button_id); 78 | void input_write_mem_savestate(file_tag_type savestate_file); 79 | void input_read_savestate(file_tag_type savestate_file); 80 | 81 | extern u32 gamepad_config_map[16]; 82 | extern u32 global_enable_analog; 83 | extern u32 analog_sensitivity_level; 84 | 85 | #endif 86 | 87 | -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | /* gameplaySP 2 | * 3 | * Copyright (C) 2006 Exophase 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License as 7 | * published by the Free Software Foundation; either version 2 of 8 | * the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #include "common.h" 21 | #include "sound.h" 22 | #include "cpu.h" 23 | #include "video.h" 24 | #ifdef PSP_BUILD 25 | 26 | //PSP_MODULE_INFO("gpSP", 0x1000, 0, 6); 27 | //PSP_MAIN_THREAD_ATTR(THREAD_ATTR_USER); 28 | 29 | void vblank_interrupt_handler(u32 sub, u32 *parg); 30 | 31 | #endif 32 | 33 | timer_type timer[4]; 34 | 35 | //debug_state current_debug_state = COUNTDOWN_BREAKPOINT; 36 | //debug_state current_debug_state = PC_BREAKPOINT; 37 | u32 breakpoint_value = 0x7c5000; 38 | debug_state current_debug_state = RUN; 39 | //u32 breakpoint_value = 0; 40 | 41 | frameskip_type current_frameskip_type = auto_frameskip; 42 | u32 frameskip_value = 4; 43 | u32 random_skip = 0; 44 | u32 global_cycles_per_instruction = 3; 45 | 46 | u32 skip_next_frame = 0; 47 | 48 | u32 frameskip_counter = 0; 49 | 50 | u32 cpu_ticks = 0; 51 | u32 frame_ticks = 0; 52 | 53 | u32 execute_cycles = 960; 54 | s32 video_count = 960; 55 | u32 ticks; 56 | 57 | u32 arm_frame = 0; 58 | u32 thumb_frame = 0; 59 | u32 last_frame = 0; 60 | 61 | u32 cycle_memory_access = 0; 62 | u32 cycle_pc_relative_access = 0; 63 | u32 cycle_sp_relative_access = 0; 64 | u32 cycle_block_memory_access = 0; 65 | u32 cycle_block_memory_sp_access = 0; 66 | u32 cycle_block_memory_words = 0; 67 | u32 cycle_dma16_words = 0; 68 | u32 cycle_dma32_words = 0; 69 | u32 flush_ram_count = 0; 70 | u32 gbc_update_count = 0; 71 | u32 oam_update_count = 0; 72 | 73 | u32 synchronize_flag = 1; 74 | 75 | u32 update_backup_flag = 1; 76 | u32 clock_speed = 333; 77 | char main_path[512]; 78 | 79 | #define check_count(count_var) \ 80 | if(count_var < execute_cycles) \ 81 | execute_cycles = count_var; \ 82 | 83 | #define check_timer(timer_number) \ 84 | if(timer[timer_number].status == TIMER_PRESCALE) \ 85 | check_count(timer[timer_number].count); \ 86 | 87 | #define update_timer(timer_number) \ 88 | if(timer[timer_number].status != TIMER_INACTIVE) \ 89 | { \ 90 | if(timer[timer_number].status != TIMER_CASCADE) \ 91 | { \ 92 | timer[timer_number].count -= execute_cycles; \ 93 | io_registers[REG_TM##timer_number##D] = \ 94 | -(timer[timer_number].count >> timer[timer_number].prescale); \ 95 | } \ 96 | \ 97 | if(timer[timer_number].count <= 0) \ 98 | { \ 99 | if(timer[timer_number].irq == TIMER_TRIGGER_IRQ) \ 100 | irq_raised |= IRQ_TIMER##timer_number; \ 101 | \ 102 | if((timer_number != 3) && \ 103 | (timer[timer_number + 1].status == TIMER_CASCADE)) \ 104 | { \ 105 | timer[timer_number + 1].count--; \ 106 | io_registers[REG_TM0D + (timer_number + 1) * 2] = \ 107 | -(timer[timer_number + 1].count); \ 108 | } \ 109 | \ 110 | if(timer_number < 2) \ 111 | { \ 112 | if(timer[timer_number].direct_sound_channels & 0x01) \ 113 | sound_timer(timer[timer_number].frequency_step, 0); \ 114 | \ 115 | if(timer[timer_number].direct_sound_channels & 0x02) \ 116 | sound_timer(timer[timer_number].frequency_step, 1); \ 117 | } \ 118 | \ 119 | timer[timer_number].count += \ 120 | (timer[timer_number].reload << timer[timer_number].prescale); \ 121 | } \ 122 | } 123 | 124 | 125 | u8 *file_ext[] = { ".gba", ".bin", ".zip", NULL }; 126 | 127 | void init_main() 128 | { 129 | u32 i; 130 | 131 | skip_next_frame = 0; 132 | 133 | for(i = 0; i < 4; i++) 134 | { 135 | dma[i].start_type = DMA_INACTIVE; 136 | dma[i].direct_sound_channel = DMA_NO_DIRECT_SOUND; 137 | timer[i].status = TIMER_INACTIVE; 138 | timer[i].reload = 0x10000; 139 | timer[i].stop_cpu_ticks = 0; 140 | } 141 | 142 | timer[0].direct_sound_channels = TIMER_DS_CHANNEL_BOTH; 143 | timer[1].direct_sound_channels = TIMER_DS_CHANNEL_NONE; 144 | 145 | cpu_ticks = 0; 146 | frame_ticks = 0; 147 | 148 | execute_cycles = 960; 149 | video_count = 960; 150 | flush_translation_cache_rom(); 151 | flush_translation_cache_ram(); 152 | flush_translation_cache_bios(); 153 | } 154 | 155 | int main(int argc, char *argv[]) 156 | { 157 | u32 i; 158 | u32 vcount = 0; 159 | u32 ticks; 160 | u32 dispstat; 161 | u8 load_filename[512]; 162 | #ifdef _arch_dreamcast 163 | fs_chdir("/cd/gbaDC/"); 164 | #endif 165 | 166 | #ifdef PSP_BUILD 167 | sceKernelRegisterSubIntrHandler(PSP_VBLANK_INT, 0, 168 | vblank_interrupt_handler, NULL); 169 | sceKernelEnableSubIntr(PSP_VBLANK_INT, 0); 170 | #else 171 | //freopen("CON", "wb", stdout); 172 | #endif 173 | printf("init_gamepak_buffer...\n"); 174 | init_gamepak_buffer(); 175 | 176 | // Copy the directory path of the executable into main_path 177 | #ifndef _arch_dreamcast 178 | getcwd(main_path); 179 | #else 180 | getcwd(main_path,512); 181 | #endif 182 | printf("load_config_file...\n"); 183 | load_config_file(); 184 | 185 | gamepak_filename[0] = 0; 186 | printf("load_bios...\n"); 187 | if(load_bios("/cd/gba_bios.bin") == -1) 188 | { 189 | #ifdef PSP_BUILD 190 | gui_action_type gui_action = CURSOR_NONE; 191 | 192 | printf("Sorry, but gpSP requires a Gameboy Advance BIOS image to run\n"); 193 | printf("correctly. Make sure to get an authentic one (search the web,\n"); 194 | printf("beg other people if you want, but don't hold me accountable\n"); 195 | printf("if you get hated or banned for it), it'll be exactly 16384\n"); 196 | printf("bytes large and should have the following md5sum value:\n\n"); 197 | printf("a860e8c0b6d573d191e4ec7db1b1e4f6\n\n"); 198 | printf("Other BIOS files might work either partially completely, I\n"); 199 | printf("really don't know.\n\n"); 200 | printf("When you do get it name it gba_bios.bin and put it in the\n"); 201 | printf("same directory as this EBOOT.\n\n"); 202 | printf("Good luck. Press any button to exit.\n"); 203 | 204 | while(gui_action == CURSOR_NONE) 205 | { 206 | gui_action = get_gui_input(); 207 | delay_us(15000); 208 | } 209 | 210 | quit(); 211 | #else 212 | printf("Sorry, but gpSP requires a Gameboy Advance BIOS image to run\n"); 213 | quit(); 214 | #endif 215 | } 216 | 217 | #ifdef PSP_BUILD 218 | delay_us(2500000); 219 | #endif 220 | printf("Initialize...\ninit_main\n"); 221 | init_main(); 222 | printf("init_sound\n"); 223 | init_sound(); 224 | printf("init_video\n"); 225 | init_video(); 226 | printf("init_input\n"); 227 | init_input(); 228 | printf("video_resolution_large\n"); 229 | video_resolution_large(); 230 | printf("Loading files...\n"); 231 | if(argc > 1) 232 | { 233 | if(load_gamepak(argv[1]) == -1) 234 | { 235 | printf("Failed to load gamepak %s, exiting.\n", load_filename); 236 | exit(-1); 237 | } 238 | 239 | set_gba_resolution(screen_scale); 240 | video_resolution_small(); 241 | 242 | init_cpu(); 243 | init_memory(); 244 | } 245 | else 246 | { 247 | 248 | if(load_file(file_ext, load_filename) == -1) 249 | { 250 | printf("Loading menu...\n"); 251 | menu(copy_screen()); 252 | } 253 | else 254 | { 255 | if(load_gamepak(load_filename) == -1) 256 | { 257 | printf("Failed to load gamepak %s, exiting.\n", load_filename); 258 | delay_us(5000000); 259 | exit(-1); 260 | } 261 | 262 | set_gba_resolution(screen_scale); 263 | video_resolution_small(); 264 | 265 | init_cpu(); 266 | init_memory(); 267 | } 268 | } 269 | 270 | last_frame = 0; 271 | 272 | // We'll never actually return from here. 273 | 274 | #ifdef PSP_BUILD 275 | execute_arm_translate(execute_cycles); 276 | #else 277 | // execute_arm_translate(execute_cycles); 278 | execute_arm(execute_cycles); 279 | #endif 280 | return 0; 281 | } 282 | 283 | void print_memory_stats(u32 *counter, u32 *region_stats, u8 *stats_str) 284 | { 285 | u32 other_region_counter = region_stats[0x1] + region_stats[0xE] + region_stats[0xF]; 286 | u32 rom_region_counter = region_stats[0x8] + region_stats[0x9] + region_stats[0xA] + 287 | region_stats[0xB] + region_stats[0xC] + region_stats[0xD]; 288 | u32 _counter = *counter; 289 | 290 | printf("memory access stats: %s (out of %d)\n", stats_str, _counter); 291 | printf("bios: %f%%\tiwram: %f%%\tewram: %f%%\tvram: %f\n", 292 | region_stats[0x0] * 100.0 / _counter, region_stats[0x3] * 100.0 / _counter, 293 | region_stats[0x2] * 100.0 / _counter, region_stats[0x6] * 100.0 / _counter); 294 | 295 | printf("oam: %f%%\tpalette: %f%%\trom: %f%%\tother: %f%%\n", 296 | region_stats[0x7] * 100.0 / _counter, region_stats[0x5] * 100.0 / _counter, 297 | rom_region_counter * 100.0 / _counter, other_region_counter * 100.0 / _counter); 298 | 299 | *counter = 0; 300 | memset(region_stats, 0, sizeof(u32) * 16); 301 | } 302 | 303 | u32 update_gba() 304 | { 305 | irq_type irq_raised = IRQ_NONE; 306 | cpu_ticks += execute_cycles; 307 | 308 | if(gbc_sound_update) 309 | { 310 | gbc_update_count++; 311 | update_gbc_sound(cpu_ticks); 312 | gbc_sound_update = 0; 313 | } 314 | 315 | update_timer(0); 316 | update_timer(1); 317 | update_timer(2); 318 | update_timer(3); 319 | 320 | video_count -= execute_cycles; 321 | 322 | if(video_count <= 0) 323 | { 324 | u32 vcount = io_registers[REG_VCOUNT]; 325 | u32 dispstat = io_registers[REG_DISPSTAT]; 326 | 327 | if((dispstat & 0x02) == 0) 328 | { 329 | // Transition from hrefresh to hblank 330 | video_count += 272; 331 | dispstat |= 0x02; 332 | 333 | if((dispstat & 0x01) == 0) 334 | { 335 | u32 i; 336 | if(oam_update) 337 | oam_update_count++; 338 | 339 | update_scanline(); 340 | 341 | 342 | // If in visible area also fire HDMA 343 | for(i = 0; i < 4; i++) 344 | { 345 | if(dma[i].start_type == DMA_START_HBLANK) 346 | gpsp_dma_transfer(dma + i); 347 | } 348 | } 349 | 350 | if(dispstat & 0x10) 351 | irq_raised |= IRQ_HBLANK; 352 | } 353 | else 354 | { 355 | // Transition from hblank to next line 356 | video_count += 960; 357 | dispstat &= ~0x02; 358 | 359 | vcount++; 360 | 361 | if(vcount == 160) 362 | { 363 | // Transition from vrefresh to vblank 364 | u32 i; 365 | 366 | dispstat |= 0x01; 367 | if(dispstat & 0x8) 368 | { 369 | irq_raised |= IRQ_VBLANK; 370 | } 371 | 372 | affine_reference_x[0] = 373 | (s32)(address32(io_registers, 0x28) << 4) >> 4; 374 | affine_reference_y[0] = 375 | (s32)(address32(io_registers, 0x2C) << 4) >> 4; 376 | affine_reference_x[1] = 377 | (s32)(address32(io_registers, 0x38) << 4) >> 4; 378 | affine_reference_y[1] = 379 | (s32)(address32(io_registers, 0x3C) << 4) >> 4; 380 | 381 | for(i = 0; i < 4; i++) 382 | { 383 | if(dma[i].start_type == DMA_START_VBLANK) 384 | gpsp_dma_transfer(dma + i); 385 | } 386 | } 387 | else 388 | 389 | if(vcount == 228) 390 | { 391 | // Transition from vblank to next screen 392 | dispstat &= ~0x01; 393 | frame_ticks++; 394 | 395 | #ifdef PSP_BUILD 396 | printf("frame update (%x), %d instructions total, %d RAM flushes\n", 397 | reg[REG_PC], instruction_count - last_frame, flush_ram_count); 398 | last_frame = instruction_count; 399 | print_memory_stats(&memory_reads_u8, memory_region_access_read_u8, 400 | "unsigned 8bit read"); 401 | print_memory_stats(&memory_reads_s8, memory_region_access_read_s8, 402 | "signed 8bit read"); 403 | print_memory_stats(&memory_reads_u16, memory_region_access_read_u16, 404 | "unsigned 16bit read"); 405 | print_memory_stats(&memory_reads_s16, memory_region_access_read_s16, 406 | "signed 16bit read"); 407 | print_memory_stats(&memory_reads_u32, memory_region_access_read_u32, 408 | "32bit read"); 409 | print_memory_stats(&memory_writes_u8, memory_region_access_write_u8, 410 | "8bit write"); 411 | print_memory_stats(&memory_writes_u16, memory_region_access_write_u16, 412 | "16bit write"); 413 | print_memory_stats(&memory_writes_u32, memory_region_access_write_u32, 414 | "32bit write"); 415 | printf("%d gbc audio updates\n", gbc_update_count); 416 | printf("%d oam updates\n", oam_update_count); 417 | gbc_update_count = 0; 418 | oam_update_count = 0; 419 | flush_ram_count = 0; 420 | #endif 421 | 422 | if(update_input()) 423 | return execute_cycles; 424 | 425 | update_gbc_sound(cpu_ticks); 426 | synchronize(); 427 | update_screen(); 428 | if(update_backup_flag) 429 | update_backup(); 430 | 431 | process_cheats(); 432 | 433 | vcount = 0; 434 | } 435 | 436 | if(vcount == (dispstat >> 8)) 437 | { 438 | // vcount trigger 439 | dispstat |= 0x04; 440 | if(dispstat & 0x20) 441 | { 442 | irq_raised |= IRQ_VCOUNT; 443 | } 444 | } 445 | else 446 | { 447 | dispstat &= ~0x04; 448 | } 449 | 450 | io_registers[REG_VCOUNT] = vcount; 451 | } 452 | io_registers[REG_DISPSTAT] = dispstat; 453 | } 454 | 455 | if(irq_raised) 456 | raise_interrupt(irq_raised); 457 | 458 | execute_cycles = video_count; 459 | 460 | check_timer(0); 461 | check_timer(1); 462 | check_timer(2); 463 | check_timer(3); 464 | 465 | return execute_cycles; 466 | } 467 | 468 | u64 last_screen_timestamp = 0; 469 | u32 frame_speed = 15000; 470 | 471 | #ifdef PSP_BUILD 472 | 473 | u32 real_frame_count = 0; 474 | u32 virtual_frame_count = 0; 475 | u32 num_skipped_frames = 0; 476 | 477 | void vblank_interrupt_handler(u32 sub, u32 *parg) 478 | { 479 | real_frame_count++; 480 | } 481 | 482 | void synchronize() 483 | { 484 | char char_buffer[64]; 485 | u64 new_ticks, time_delta; 486 | s32 used_frameskip = frameskip_value; 487 | 488 | if(!synchronize_flag) 489 | { 490 | print_string("--FF--", 0xFFFF, 0x000, 0, 0); 491 | used_frameskip = 4; 492 | virtual_frame_count = real_frame_count - 1; 493 | } 494 | 495 | skip_next_frame = 0; 496 | 497 | virtual_frame_count++; 498 | 499 | if(real_frame_count >= virtual_frame_count) 500 | { 501 | if((real_frame_count > virtual_frame_count) && 502 | (current_frameskip_type == auto_frameskip) && 503 | (num_skipped_frames < frameskip_value)) 504 | { 505 | skip_next_frame = 1; 506 | num_skipped_frames++; 507 | } 508 | else 509 | { 510 | virtual_frame_count = real_frame_count; 511 | num_skipped_frames = 0; 512 | } 513 | 514 | // Here so that the home button return will eventually work. 515 | // If it's not running fullspeed anyway this won't really hurt 516 | // it much more. 517 | 518 | delay_us(1); 519 | } 520 | else 521 | { 522 | if(synchronize_flag) 523 | sceDisplayWaitVblankStart(); 524 | } 525 | 526 | if(current_frameskip_type == manual_frameskip) 527 | { 528 | frameskip_counter = (frameskip_counter + 1) % 529 | (used_frameskip + 1); 530 | if(random_skip) 531 | { 532 | if(frameskip_counter != (rand() % (used_frameskip + 1))) 533 | skip_next_frame = 1; 534 | } 535 | else 536 | { 537 | if(frameskip_counter) 538 | skip_next_frame = 1; 539 | } 540 | } 541 | 542 | /* sprintf(char_buffer, "%08d %08d %d %d %d\n", 543 | real_frame_count, virtual_frame_count, num_skipped_frames, 544 | real_frame_count - virtual_frame_count, skip_next_frame); 545 | print_string(char_buffer, 0xFFFF, 0x0000, 0, 10); */ 546 | 547 | /* 548 | sprintf(char_buffer, "%02d %02d %06d %07d", frameskip, (u32)ms_needed, 549 | ram_translation_ptr - ram_translation_cache, rom_translation_ptr - 550 | rom_translation_cache); 551 | print_string(char_buffer, 0xFFFF, 0x0000, 0, 0); 552 | */ 553 | } 554 | 555 | #else 556 | 557 | u32 ticks_needed_total = 0; 558 | float us_needed = 0.0; 559 | u32 frames = 0; 560 | const u32 frame_interval = 60; 561 | 562 | void synchronize() 563 | { 564 | u64 new_ticks; 565 | u64 time_delta; 566 | char char_buffer[64]; 567 | 568 | get_ticks_us(&new_ticks); 569 | time_delta = new_ticks - last_screen_timestamp; 570 | last_screen_timestamp = new_ticks; 571 | ticks_needed_total += time_delta; 572 | 573 | skip_next_frame = 0; 574 | 575 | if((time_delta < frame_speed) && synchronize_flag) 576 | { 577 | delay_us(frame_speed - time_delta); 578 | } 579 | 580 | frames++; 581 | 582 | if(frames == frame_interval) 583 | { 584 | us_needed = (float)ticks_needed_total / frame_interval; 585 | ticks_needed_total = 0; 586 | frames = 0; 587 | } 588 | 589 | if(current_frameskip_type == manual_frameskip) 590 | { 591 | frameskip_counter = (frameskip_counter + 1) % 592 | (frameskip_value + 1); 593 | if(random_skip) 594 | { 595 | if(frameskip_counter != (rand() % (frameskip_value + 1))) 596 | skip_next_frame = 1; 597 | } 598 | else 599 | { 600 | if(frameskip_counter) 601 | skip_next_frame = 1; 602 | } 603 | } 604 | 605 | if(synchronize_flag == 0) 606 | print_string("--FF--", 0xFFFF, 0x000, 0, 0); 607 | 608 | sprintf(char_buffer, "gpSP: %.1fms %.1ffps", us_needed / 1000.0, 609 | 1000000.0 / us_needed); 610 | SDL_WM_SetCaption(char_buffer, "gpSP"); 611 | 612 | /* 613 | sprintf(char_buffer, "%02d %02d %06d %07d", frameskip, (u32)ms_needed, 614 | ram_translation_ptr - ram_translation_cache, rom_translation_ptr - 615 | rom_translation_cache); 616 | print_string(char_buffer, 0xFFFF, 0x0000, 0, 0); 617 | */ 618 | } 619 | 620 | #endif 621 | 622 | void quit() 623 | { 624 | if(!update_backup_flag) 625 | update_backup_force(); 626 | 627 | sound_exit(); 628 | 629 | #ifdef PSP_BUILD 630 | sceKernelExitGame(); 631 | #else 632 | SDL_Quit(); 633 | exit(0); 634 | #endif 635 | } 636 | 637 | void reset_gba() 638 | { 639 | init_main(); 640 | init_memory(); 641 | init_cpu(); 642 | reset_sound(); 643 | } 644 | 645 | #ifdef PSP_BUILD 646 | 647 | u32 file_length(u8 *filename, s32 dummy) 648 | { 649 | SceIoStat stats; 650 | sceIoGetstat(filename, &stats); 651 | return stats.st_size; 652 | } 653 | 654 | void delay_us(u32 us_count) 655 | { 656 | sceKernelDelayThread(us_count); 657 | } 658 | 659 | void get_ticks_us(u64 *tick_return) 660 | { 661 | u64 ticks; 662 | sceRtcGetCurrentTick(&ticks); 663 | 664 | *tick_return = (ticks * 1000000) / sceRtcGetTickResolution(); 665 | } 666 | 667 | #else 668 | 669 | u32 file_length(u8 *dummy, FILE *fp) 670 | { 671 | u32 length; 672 | 673 | fseek(fp, 0, SEEK_END); 674 | length = ftell(fp); 675 | fseek(fp, 0, SEEK_SET); 676 | 677 | return length; 678 | } 679 | 680 | void delay_us(u32 us_count) 681 | { 682 | SDL_Delay(us_count / 1000); 683 | } 684 | 685 | void get_ticks_us(u64 *ticks_return) 686 | { 687 | *ticks_return = (SDL_GetTicks() * 1000); 688 | } 689 | 690 | #endif 691 | 692 | void change_ext(u8 *src, u8 *buffer, u8 *extension) 693 | { 694 | u8 *dot_position; 695 | strcpy(buffer, src); 696 | dot_position = strrchr(buffer, '.'); 697 | 698 | if(dot_position) 699 | strcpy(dot_position, extension); 700 | } 701 | 702 | #define main_savestate_builder(type) \ 703 | void main_##type##_savestate(file_tag_type savestate_file) \ 704 | { \ 705 | file_##type##_variable(savestate_file, cpu_ticks); \ 706 | file_##type##_variable(savestate_file, execute_cycles); \ 707 | file_##type##_variable(savestate_file, video_count); \ 708 | file_##type##_array(savestate_file, timer); \ 709 | } \ 710 | 711 | main_savestate_builder(read); 712 | main_savestate_builder(write_mem); 713 | 714 | void print_out(u32 address, u32 pc) 715 | { 716 | char buffer[256]; 717 | sprintf(buffer, "patching from gp8 %x", address); 718 | print_string(buffer, 0xFFFF, 0x0000, 0, 0); 719 | update_screen(); 720 | delay_us(5000000); 721 | } 722 | -------------------------------------------------------------------------------- /main.h: -------------------------------------------------------------------------------- 1 | /* gameplaySP 2 | * 3 | * Copyright (C) 2006 Exophase 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License as 7 | * published by the Free Software Foundation; either version 2 of 8 | * the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #ifndef MAIN_H 21 | #define MAIN_H 22 | 23 | typedef enum 24 | { 25 | TIMER_INACTIVE, 26 | TIMER_PRESCALE, 27 | TIMER_CASCADE 28 | } timer_status_type; 29 | 30 | typedef enum 31 | { 32 | TIMER_NO_IRQ, 33 | TIMER_TRIGGER_IRQ 34 | } timer_irq_type; 35 | 36 | 37 | typedef enum 38 | { 39 | TIMER_DS_CHANNEL_NONE, 40 | TIMER_DS_CHANNEL_A, 41 | TIMER_DS_CHANNEL_B, 42 | TIMER_DS_CHANNEL_BOTH 43 | } timer_ds_channel_type; 44 | 45 | typedef struct 46 | { 47 | s32 count; 48 | u32 reload; 49 | u32 prescale; 50 | u32 stop_cpu_ticks; 51 | fixed16_16 frequency_step; 52 | timer_ds_channel_type direct_sound_channels; 53 | timer_irq_type irq; 54 | timer_status_type status; 55 | } timer_type; 56 | 57 | typedef enum 58 | { 59 | auto_frameskip, 60 | manual_frameskip, 61 | no_frameskip 62 | } frameskip_type; 63 | 64 | extern u32 cpu_ticks; 65 | extern u32 frame_ticks; 66 | extern u32 execute_cycles; 67 | extern frameskip_type current_frameskip_type; 68 | extern u32 frameskip_value; 69 | extern u32 random_skip; 70 | extern u32 global_cycles_per_instruction; 71 | extern u32 synchronize_flag; 72 | extern u32 skip_next_frame; 73 | 74 | extern timer_type timer[4]; 75 | static u32 prescale_table[] = { 0, 6, 8, 10 }; 76 | 77 | extern u32 cycle_memory_access; 78 | extern u32 cycle_pc_relative_access; 79 | extern u32 cycle_sp_relative_access; 80 | extern u32 cycle_block_memory_access; 81 | extern u32 cycle_block_memory_sp_access; 82 | extern u32 cycle_block_memory_words; 83 | extern u32 cycle_dma16_words; 84 | extern u32 cycle_dma32_words; 85 | extern u32 flush_ram_count; 86 | 87 | extern u64 base_timestamp; 88 | 89 | extern char main_path[512]; 90 | 91 | extern u32 update_backup_flag; 92 | extern u32 clock_speed; 93 | 94 | u32 update_gba(); 95 | void reset_gba(); 96 | void synchronize(); 97 | void quit(); 98 | void delay_us(u32 us_count); 99 | void get_ticks_us(u64 *tick_return); 100 | void game_name_ext(u8 *src, u8 *buffer, u8 *extension); 101 | void main_write_mem_savestate(file_tag_type savestate_file); 102 | void main_read_savestate(file_tag_type savestate_file); 103 | 104 | #ifdef PSP_BUILD 105 | 106 | u32 file_length(u8 *filename, s32 dummy); 107 | 108 | extern u32 real_frame_count; 109 | extern u32 virtual_frame_count; 110 | extern u32 max_frameskip; 111 | extern u32 num_skipped_frames; 112 | 113 | #else 114 | 115 | u32 file_length(u8 *dummy, FILE *fp); 116 | 117 | #endif 118 | 119 | #define count_timer(timer_number) \ 120 | timer[timer_number].reload = 0x10000 - value; \ 121 | if(timer_number < 2) \ 122 | { \ 123 | u32 timer_reload = \ 124 | timer[timer_number].reload << timer[timer_number].prescale; \ 125 | sound_update_frequency_step(timer_number); \ 126 | } \ 127 | 128 | #define adjust_sound_buffer(timer_number, channel) \ 129 | if(timer[timer_number].direct_sound_channels & (0x01 << channel)) \ 130 | { \ 131 | direct_sound_channel[channel].buffer_index = \ 132 | (direct_sound_channel[channel].buffer_index + buffer_adjust) % \ 133 | BUFFER_SIZE; \ 134 | } \ 135 | 136 | #define trigger_timer(timer_number) \ 137 | if(value & 0x80) \ 138 | { \ 139 | if(timer[timer_number].status == TIMER_INACTIVE) \ 140 | { \ 141 | u32 prescale = prescale_table[value & 0x03]; \ 142 | u32 timer_reload = timer[timer_number].reload; \ 143 | \ 144 | if((value >> 2) & 0x01) \ 145 | timer[timer_number].status = TIMER_CASCADE; \ 146 | else \ 147 | timer[timer_number].status = TIMER_PRESCALE; \ 148 | \ 149 | timer[timer_number].prescale = prescale; \ 150 | timer[timer_number].irq = (value >> 6) & 0x01; \ 151 | \ 152 | address16(io_registers, 0x100 + (timer_number * 4)) = \ 153 | -timer_reload; \ 154 | \ 155 | timer_reload <<= prescale; \ 156 | timer[timer_number].count = timer_reload; \ 157 | \ 158 | if(timer_reload < execute_cycles) \ 159 | execute_cycles = timer_reload; \ 160 | \ 161 | if(timer_number < 2) \ 162 | { \ 163 | u32 buffer_adjust = \ 164 | (u32)(((float)(cpu_ticks - timer[timer_number].stop_cpu_ticks) * \ 165 | sound_frequency) / 16777216.0) * 2; \ 166 | \ 167 | sound_update_frequency_step(timer_number); \ 168 | adjust_sound_buffer(timer_number, 0); \ 169 | adjust_sound_buffer(timer_number, 1); \ 170 | } \ 171 | } \ 172 | } \ 173 | else \ 174 | { \ 175 | if(timer[timer_number].status != TIMER_INACTIVE) \ 176 | { \ 177 | timer[timer_number].status = TIMER_INACTIVE; \ 178 | timer[timer_number].stop_cpu_ticks = cpu_ticks; \ 179 | } \ 180 | } \ 181 | address16(io_registers, 0x102 + (timer_number * 4)) = value; \ 182 | 183 | #endif 184 | 185 | 186 | -------------------------------------------------------------------------------- /memory.h: -------------------------------------------------------------------------------- 1 | /* gameplaySP 2 | * 3 | * Copyright (C) 2006 Exophase 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License as 7 | * published by the Free Software Foundation; either version 2 of 8 | * the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #ifndef MEMORY_H 21 | #define MEMORY_H 22 | 23 | void init_gamepak_buffer(); 24 | u32 load_file_zip(); 25 | 26 | typedef enum 27 | { 28 | DMA_START_IMMEDIATELY, 29 | DMA_START_VBLANK, 30 | DMA_START_HBLANK, 31 | DMA_START_SPECIAL, 32 | DMA_INACTIVE 33 | } dma_start_type; 34 | 35 | typedef enum 36 | { 37 | DMA_16BIT, 38 | DMA_32BIT 39 | } dma_length_type; 40 | 41 | typedef enum 42 | { 43 | DMA_NO_REPEAT, 44 | DMA_REPEAT 45 | } dma_repeat_type; 46 | 47 | typedef enum 48 | { 49 | DMA_INCREMENT, 50 | DMA_DECREMENT, 51 | DMA_FIXED, 52 | DMA_RELOAD 53 | } dma_increment_type; 54 | 55 | typedef enum 56 | { 57 | DMA_NO_IRQ, 58 | DMA_TRIGGER_IRQ 59 | } dma_irq_type; 60 | 61 | typedef enum 62 | { 63 | DMA_DIRECT_SOUND_A, 64 | DMA_DIRECT_SOUND_B, 65 | DMA_NO_DIRECT_SOUND 66 | } dma_ds_type; 67 | 68 | typedef struct 69 | { 70 | u32 dma_channel; 71 | u32 source_address; 72 | u32 dest_address; 73 | u32 length; 74 | dma_repeat_type repeat_type; 75 | dma_ds_type direct_sound_channel; 76 | dma_increment_type source_direction; 77 | dma_increment_type dest_direction; 78 | dma_length_type length_type; 79 | dma_start_type start_type; 80 | dma_irq_type irq; 81 | } dma_transfer_type; 82 | 83 | typedef enum 84 | { 85 | REG_DISPCNT = 0x000, 86 | REG_DISPSTAT = 0x002, 87 | REG_VCOUNT = 0x003, 88 | REG_BG0CNT = 0x004, 89 | REG_BG1CNT = 0x005, 90 | REG_BG2CNT = 0x006, 91 | REG_BG3CNT = 0x007, 92 | REG_BG0HOFS = 0x08, 93 | REG_BG0VOFS = 0x09, 94 | REG_BG1HOFS = 0x0A, 95 | REG_BG1VOFS = 0x0B, 96 | REG_BG2HOFS = 0x0C, 97 | REG_BG2VOFS = 0x0D, 98 | REG_BG3HOFS = 0x0E, 99 | REG_BG3VOFS = 0x0F, 100 | REG_BG2PA = 0x10, 101 | REG_BG2PB = 0x11, 102 | REG_BG2PC = 0x12, 103 | REG_BG2PD = 0x13, 104 | REG_BG2X_L = 0x14, 105 | REG_BG2X_H = 0x15, 106 | REG_BG2Y_L = 0x16, 107 | REG_BG2Y_H = 0x17, 108 | REG_BG3PA = 0x18, 109 | REG_BG3PB = 0x19, 110 | REG_BG3PC = 0x1A, 111 | REG_BG3PD = 0x1B, 112 | REG_BG3X_L = 0x1C, 113 | REG_BG3X_H = 0x1D, 114 | REG_BG3Y_L = 0x1E, 115 | REG_BG3Y_H = 0x1F, 116 | REG_WIN0H = 0x20, 117 | REG_WIN1H = 0x21, 118 | REG_WIN0V = 0x22, 119 | REG_WIN1V = 0x23, 120 | REG_WININ = 0x24, 121 | REG_WINOUT = 0x25, 122 | REG_BLDCNT = 0x28, 123 | REG_BLDALPHA = 0x29, 124 | REG_BLDY = 0x2A, 125 | REG_TM0D = 0x80, 126 | REG_TM0CNT = 0x81, 127 | REG_TM1D = 0x82, 128 | REG_TM1CNT = 0x83, 129 | REG_TM2D = 0x84, 130 | REG_TM2CNT = 0x85, 131 | REG_TM3D = 0x86, 132 | REG_TM3CNT = 0x87, 133 | REG_P1 = 0x098, 134 | REG_P1CNT = 0x099, 135 | REG_RCNT = 0x9A, 136 | REG_IE = 0x100, 137 | REG_IF = 0x101, 138 | REG_IME = 0x104, 139 | REG_HALTCNT = 0x180 140 | } hardware_register; 141 | 142 | typedef enum 143 | { 144 | FLASH_DEVICE_MACRONIX_64KB = 0x1C, 145 | FLASH_DEVICE_AMTEL_64KB = 0x3D, 146 | FLASH_DEVICE_SST_64K = 0xD4, 147 | FLASH_DEVICE_PANASONIC_64KB = 0x1B, 148 | FLASH_DEVICE_MACRONIX_128KB = 0x09 149 | } flash_device_id_type; 150 | 151 | typedef enum 152 | { 153 | FLASH_MANUFACTURER_MACRONIX = 0xC2, 154 | FLASH_MANUFACTURER_AMTEL = 0x1F, 155 | FLASH_MANUFACTURER_PANASONIC = 0x32, 156 | FLASH_MANUFACTURER_SST = 0xBF 157 | } flash_manufacturer_id_type; 158 | 159 | u8 function_cc read_memory8(u32 address); 160 | u32 function_cc read_memory16(u32 address); 161 | u16 function_cc read_memory16_signed(u32 address); 162 | u32 function_cc read_memory32(u32 address); 163 | cpu_alert_type function_cc write_memory8(u32 address, u8 value); 164 | cpu_alert_type function_cc write_memory16(u32 address, u16 value); 165 | cpu_alert_type function_cc write_memory32(u32 address, u32 value); 166 | 167 | extern u8 *memory_regions[16]; 168 | extern u32 memory_limits[16]; 169 | 170 | extern u32 waitstate_cycles_sequential[16][3]; 171 | 172 | extern u32 gamepak_size; 173 | extern u8 gamepak_title[13]; 174 | extern u8 gamepak_code[5]; 175 | extern u8 gamepak_maker[3]; 176 | extern u8 gamepak_filename[512]; 177 | 178 | cpu_alert_type gpsp_dma_transfer(dma_transfer_type *dma); 179 | u8 *memory_region(u32 address, u32 *memory_limit); 180 | u32 load_gamepak(char *name); 181 | u32 load_backup(char *name); 182 | s32 load_bios(char *name); 183 | void update_backup(); 184 | void update_backup_force(); 185 | void init_memory(); 186 | u8 *load_gamepak_page(u32 physical_index); 187 | void memory_write_mem_savestate(file_tag_type savestate_file); 188 | void memory_read_savestate(file_tag_type savestate_file); 189 | void load_state(char *savestate_filename); 190 | void save_state(char *savestate_filename, u16 *screen_capture); 191 | 192 | extern u8 *gamepak_rom; 193 | extern u32 gamepak_ram_buffer_size; 194 | extern u32 oam_update; 195 | extern u32 gbc_sound_update; 196 | extern u32 gbc_sound_wave_update; 197 | extern dma_transfer_type dma[4]; 198 | 199 | extern u8 *write_mem_ptr; 200 | 201 | #ifdef PSP_BUILD_VRAM_STORAGE 202 | 203 | extern u16 *io_registers; 204 | extern u8 *ewram; 205 | extern u8 *iwram; 206 | extern u8 *vram; 207 | extern u16 *palette_ram; 208 | extern u16 *oam_ram; 209 | extern u16 *palette_ram_converted; 210 | //extern u8 *bios_rom; 211 | 212 | #else 213 | 214 | extern u16 palette_ram[512]; 215 | extern u16 oam_ram[512]; 216 | extern u16 palette_ram_converted[512]; 217 | extern u16 io_registers[1024 * 16]; 218 | extern u8 ewram[1024 * 256 * 2]; 219 | extern u8 iwram[1024 * 32 * 2]; 220 | extern u8 vram[1024 * 96 * 2]; 221 | 222 | #endif 223 | 224 | extern u8 bios_rom[1024 * 32]; 225 | extern u32 bios_read_protect; 226 | 227 | extern u8 *memory_map_read[8 * 1024]; 228 | extern u32 reg[64]; 229 | extern u8 *memory_map_write[8 * 1024]; 230 | 231 | extern flash_device_id_type flash_device_id; 232 | 233 | #endif 234 | -------------------------------------------------------------------------------- /psp/ICON0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GPF/gPSPDC/9887759aee122eefff3cab6d7d9109ed34de60ee/psp/ICON0.png -------------------------------------------------------------------------------- /psp/Makefile: -------------------------------------------------------------------------------- 1 | # gpSP makefile 2 | # Gilead Kutnick - Exophase 3 | 4 | # Global definitions 5 | 6 | PSPSDK = ${shell psp-config --pspsdk-path} 7 | PREFIX = ${shell psp-config --psp-prefix} 8 | 9 | OBJS = main.o cpu.o video.o memory.o sound.o input.o \ 10 | cpu_threaded.o gui.o zip.o mips_stub.o 11 | 12 | TARGET = gpSP 13 | 14 | VPATH += .. 15 | CFLAGS += -O3 -DPSP_BUILD -G0 16 | CFLAGS += ${shell ${PREFIX}/bin/sdl-config --cflags} 17 | CXXFLAGS = ${CFLAGS} -fno-exceptions -fno-rtti 18 | ASFLAGS = ${CFLAGS} 19 | PSP_EBOOT_TITLE = gpSP 20 | EXTRA_TARGETS = EBOOT.PBP 21 | 22 | LIBS += ${shell ${PREFIX}/bin/sdl-config --libs} -lpsppower \ 23 | -lz 24 | 25 | include ${PSPSDK}/lib/build.mak 26 | 27 | -------------------------------------------------------------------------------- /psp/PIC1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GPF/gPSPDC/9887759aee122eefff3cab6d7d9109ed34de60ee/psp/PIC1.png -------------------------------------------------------------------------------- /sound.h: -------------------------------------------------------------------------------- 1 | /* gameplaySP 2 | * 3 | * Copyright (C) 2006 Exophase 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License as 7 | * published by the Free Software Foundation; either version 2 of 8 | * the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #ifndef SOUND_H 21 | #define SOUND_H 22 | 23 | void reset_sound(); 24 | void sound_exit(); 25 | #define BUFFER_SIZE 32768 26 | 27 | // A lot of sound cards on PC can't handle such small buffers but this 28 | // seems to work well on PSP. 29 | 30 | #ifdef PSP_BUILD 31 | 32 | #define SOUND_BUFFER_SIZE 8192 33 | 34 | #else 35 | 36 | #define SOUND_BUFFER_SIZE 8192 37 | 38 | #endif 39 | 40 | typedef enum 41 | { 42 | DIRECT_SOUND_INACTIVE, 43 | DIRECT_SOUND_RIGHT, 44 | DIRECT_SOUND_LEFT, 45 | DIRECT_SOUND_LEFTRIGHT 46 | } direct_sound_status_type; 47 | 48 | typedef enum 49 | { 50 | DIRECT_SOUND_VOLUME_50, 51 | DIRECT_SOUND_VOLUME_100 52 | } direct_sound_volume_type; 53 | 54 | typedef struct 55 | { 56 | s8 fifo[32]; 57 | u32 fifo_base; 58 | u32 fifo_top; 59 | fixed16_16 fifo_fractional; 60 | // The + 1 is to give some extra room for linear interpolation 61 | // when wrapping around. 62 | u32 buffer_index; 63 | direct_sound_status_type status; 64 | direct_sound_volume_type volume; 65 | u32 last_cpu_ticks; 66 | } direct_sound_struct; 67 | 68 | typedef enum 69 | { 70 | GBC_SOUND_INACTIVE, 71 | GBC_SOUND_RIGHT, 72 | GBC_SOUND_LEFT, 73 | GBC_SOUND_LEFTRIGHT 74 | } gbc_sound_status_type; 75 | 76 | 77 | typedef struct 78 | { 79 | u32 rate; 80 | fixed16_16 frequency_step; 81 | fixed16_16 sample_index; 82 | fixed16_16 tick_counter; 83 | u32 total_volume; 84 | u32 envelope_initial_volume; 85 | u32 envelope_volume; 86 | u32 envelope_direction; 87 | u32 envelope_status; 88 | u32 envelope_step; 89 | u32 envelope_ticks; 90 | u32 envelope_initial_ticks; 91 | u32 sweep_status; 92 | u32 sweep_direction; 93 | u32 sweep_ticks; 94 | u32 sweep_initial_ticks; 95 | u32 sweep_shift; 96 | u32 length_status; 97 | u32 length_ticks; 98 | u32 noise_type; 99 | u32 wave_type; 100 | u32 wave_bank; 101 | u32 wave_volume; 102 | gbc_sound_status_type status; 103 | u32 active_flag; 104 | u32 master_enable; 105 | s8 *sample_data; 106 | } gbc_sound_struct; 107 | 108 | extern direct_sound_struct direct_sound_channel[2]; 109 | extern gbc_sound_struct gbc_sound_channel[4]; 110 | extern s8 square_pattern_duty[4][8]; 111 | extern u32 gbc_sound_master_volume_left; 112 | extern u32 gbc_sound_master_volume_right; 113 | extern u32 gbc_sound_master_volume; 114 | 115 | extern u32 sound_frequency; 116 | extern u32 sound_on; 117 | 118 | extern u32 global_enable_audio; 119 | extern u32 enable_low_pass_filter; 120 | extern u32 audio_buffer_size_number; 121 | 122 | extern SDL_mutex *sound_mutex; 123 | extern SDL_cond *sound_cv; 124 | 125 | void sound_timer_queue8(u32 channel, u8 value); 126 | void sound_timer_queue16(u32 channel, u16 value); 127 | void sound_timer_queue32(u32 channel, u32 value); 128 | void sound_timer(fixed16_16 frequency_step, u32 channel); 129 | void sound_reset_fifo(u32 channel); 130 | void update_gbc_sound(u32 cpu_ticks); 131 | void init_sound(); 132 | void sound_write_mem_savestate(file_tag_type savestate_file); 133 | void sound_read_savestate(file_tag_type savestate_file); 134 | 135 | #define gbc_sound_tone_control_low(channel, address) \ 136 | { \ 137 | u32 initial_volume = (value >> 12) & 0x0F; \ 138 | u32 envelope_ticks = ((value >> 8) & 0x07) * 4; \ 139 | gbc_sound_channel[channel].length_ticks = 64 - (value & 0x3F); \ 140 | gbc_sound_channel[channel].sample_data = \ 141 | square_pattern_duty[(value >> 6) & 0x03]; \ 142 | gbc_sound_channel[channel].envelope_direction = (value >> 11) & 0x01; \ 143 | gbc_sound_channel[channel].envelope_initial_volume = initial_volume; \ 144 | gbc_sound_channel[channel].envelope_volume = initial_volume; \ 145 | gbc_sound_channel[channel].envelope_initial_ticks = envelope_ticks; \ 146 | gbc_sound_channel[channel].envelope_ticks = envelope_ticks; \ 147 | gbc_sound_channel[channel].envelope_status = (envelope_ticks != 0); \ 148 | gbc_sound_channel[channel].envelope_volume = initial_volume; \ 149 | gbc_sound_update = 1; \ 150 | address16(io_registers, address) = value; \ 151 | } \ 152 | 153 | #define gbc_sound_tone_control_high(channel, address) \ 154 | { \ 155 | u32 rate = value & 0x7FF; \ 156 | gbc_sound_channel[channel].rate = rate; \ 157 | gbc_sound_channel[channel].frequency_step = \ 158 | float_to_fp16_16(((131072.0 / (2048 - rate)) * 8.0) / sound_frequency); \ 159 | gbc_sound_channel[channel].length_status = (value >> 14) & 0x01; \ 160 | if(value & 0x8000) \ 161 | { \ 162 | gbc_sound_channel[channel].active_flag = 1; \ 163 | gbc_sound_channel[channel].sample_index -= float_to_fp16_16(1.0 / 12.0); \ 164 | gbc_sound_channel[channel].envelope_ticks = \ 165 | gbc_sound_channel[channel].envelope_initial_ticks; \ 166 | gbc_sound_channel[channel].envelope_volume = \ 167 | gbc_sound_channel[channel].envelope_initial_volume; \ 168 | } \ 169 | \ 170 | gbc_sound_update = 1; \ 171 | address16(io_registers, address) = value; \ 172 | } \ 173 | 174 | #define gbc_sound_tone_control_sweep() \ 175 | { \ 176 | u32 sweep_ticks = ((value >> 4) & 0x07) * 2; \ 177 | gbc_sound_channel[0].sweep_shift = value & 0x07; \ 178 | gbc_sound_channel[0].sweep_direction = (value >> 3) & 0x01; \ 179 | gbc_sound_channel[0].sweep_status = (value != 8); \ 180 | gbc_sound_channel[0].sweep_ticks = sweep_ticks; \ 181 | gbc_sound_channel[0].sweep_initial_ticks = sweep_ticks; \ 182 | gbc_sound_update = 1; \ 183 | address16(io_registers, 0x60) = value; \ 184 | } \ 185 | 186 | #define gbc_sound_wave_control() \ 187 | { \ 188 | gbc_sound_channel[2].wave_type = (value >> 5) & 0x01; \ 189 | gbc_sound_channel[2].wave_bank = (value >> 6) & 0x01; \ 190 | if(value & 0x80) \ 191 | { \ 192 | gbc_sound_channel[2].master_enable = 1; \ 193 | } \ 194 | else \ 195 | { \ 196 | gbc_sound_channel[2].master_enable = 0; \ 197 | } \ 198 | \ 199 | gbc_sound_update = 1; \ 200 | address16(io_registers, 0x70) = value; \ 201 | } \ 202 | 203 | static u32 gbc_sound_wave_volume[4] = { 0, 16384, 8192, 4096 }; 204 | 205 | #define gbc_sound_tone_control_low_wave() \ 206 | { \ 207 | gbc_sound_channel[2].length_ticks = 256 - (value & 0xFF); \ 208 | if((value >> 15) & 0x01) \ 209 | { \ 210 | gbc_sound_channel[2].wave_volume = 12288; \ 211 | } \ 212 | else \ 213 | { \ 214 | gbc_sound_channel[2].wave_volume = \ 215 | gbc_sound_wave_volume[(value >> 13) & 0x03]; \ 216 | } \ 217 | gbc_sound_update = 1; \ 218 | address16(io_registers, 0x72) = value; \ 219 | } \ 220 | 221 | #define gbc_sound_tone_control_high_wave() \ 222 | { \ 223 | u32 rate = value & 0x7FF; \ 224 | gbc_sound_channel[2].rate = rate; \ 225 | gbc_sound_channel[2].frequency_step = \ 226 | float_to_fp16_16((2097152.0 / (2048 - rate)) / sound_frequency); \ 227 | gbc_sound_channel[2].length_status = (value >> 14) & 0x01; \ 228 | if(value & 0x8000) \ 229 | { \ 230 | gbc_sound_channel[2].sample_index = 0; \ 231 | gbc_sound_channel[2].active_flag = 1; \ 232 | } \ 233 | gbc_sound_update = 1; \ 234 | address16(io_registers, 0x74) = value; \ 235 | } \ 236 | 237 | #define gbc_sound_noise_control() \ 238 | { \ 239 | u32 dividing_ratio = value & 0x07; \ 240 | u32 frequency_shift = (value >> 4) & 0x0F; \ 241 | if(dividing_ratio == 0) \ 242 | { \ 243 | gbc_sound_channel[3].frequency_step = \ 244 | float_to_fp16_16(1048576.0 / (1 << (frequency_shift + 1)) / \ 245 | sound_frequency); \ 246 | } \ 247 | else \ 248 | { \ 249 | gbc_sound_channel[3].frequency_step = \ 250 | float_to_fp16_16(524288.0 / (dividing_ratio * \ 251 | (1 << (frequency_shift + 1))) / sound_frequency); \ 252 | } \ 253 | gbc_sound_channel[3].noise_type = (value >> 3) & 0x01; \ 254 | gbc_sound_channel[3].length_status = (value >> 14) & 0x01; \ 255 | if(value & 0x8000) \ 256 | { \ 257 | gbc_sound_channel[3].sample_index = 0; \ 258 | gbc_sound_channel[3].active_flag = 1; \ 259 | gbc_sound_channel[3].envelope_ticks = \ 260 | gbc_sound_channel[3].envelope_initial_ticks; \ 261 | gbc_sound_channel[3].envelope_volume = \ 262 | gbc_sound_channel[3].envelope_initial_volume; \ 263 | } \ 264 | gbc_sound_update = 1; \ 265 | address16(io_registers, 0x7C) = value; \ 266 | } \ 267 | 268 | #define gbc_trigger_sound_channel(channel) \ 269 | gbc_sound_master_volume_right = value & 0x07; \ 270 | gbc_sound_master_volume_left = (value >> 4) & 0x07; \ 271 | gbc_sound_channel[channel].status = ((value >> (channel + 8)) & 0x01) | \ 272 | ((value >> (channel + 11)) & 0x03) \ 273 | 274 | #define gbc_trigger_sound() \ 275 | { \ 276 | gbc_trigger_sound_channel(0); \ 277 | gbc_trigger_sound_channel(1); \ 278 | gbc_trigger_sound_channel(2); \ 279 | gbc_trigger_sound_channel(3); \ 280 | address16(io_registers, 0x80) = value; \ 281 | } \ 282 | 283 | #define trigger_sound() \ 284 | { \ 285 | timer[0].direct_sound_channels = (((value >> 10) & 0x01) == 0) | \ 286 | ((((value >> 14) & 0x01) == 0) << 1); \ 287 | timer[1].direct_sound_channels = (((value >> 10) & 0x01) == 1) | \ 288 | ((((value >> 14) & 0x01) == 1) << 1); \ 289 | direct_sound_channel[0].volume = (value >> 2) & 0x01; \ 290 | direct_sound_channel[0].status = (value >> 8) & 0x03; \ 291 | direct_sound_channel[1].volume = (value >> 3) & 0x01; \ 292 | direct_sound_channel[1].status = (value >> 12) & 0x03; \ 293 | gbc_sound_master_volume = value & 0x03; \ 294 | \ 295 | if((value >> 11) & 0x01) \ 296 | sound_reset_fifo(0); \ 297 | if((value >> 15) & 0x01) \ 298 | sound_reset_fifo(1); \ 299 | address16(io_registers, 0x82) = value; \ 300 | } \ 301 | 302 | #define sound_on() \ 303 | if(value & 0x80) \ 304 | { \ 305 | if(sound_on != 1) \ 306 | { \ 307 | sound_on = 1; \ 308 | } \ 309 | } \ 310 | else \ 311 | { \ 312 | u32 i; \ 313 | for(i = 0; i < 4; i++) \ 314 | { \ 315 | gbc_sound_channel[i].active_flag = 0; \ 316 | } \ 317 | sound_on = 0; \ 318 | } \ 319 | address16(io_registers, 0x84) = \ 320 | (address16(io_registers, 0x84) & 0x000F) | (value & 0xFFF0); \ 321 | 322 | #define sound_update_frequency_step(timer_number) \ 323 | timer[timer_number].frequency_step = \ 324 | float_to_fp16_16(16777216.0 / (timer_reload * sound_frequency)) \ 325 | 326 | 327 | #endif 328 | -------------------------------------------------------------------------------- /video.h: -------------------------------------------------------------------------------- 1 | /* gameplaySP 2 | * 3 | * Copyright (C) 2006 Exophase 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License as 7 | * published by the Free Software Foundation; either version 2 of 8 | * the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #ifndef VIDEO_H 21 | #define VIDEO_H 22 | 23 | void update_scanline(); 24 | void update_screen(); 25 | void init_video(); 26 | void video_resolution_large(); 27 | void video_resolution_small(); 28 | void print_string(const char *str, u16 fg_color, u16 bg_color, 29 | u32 x, u32 y); 30 | void print_string_pad(const char *str, u16 fg_color, u16 bg_color, 31 | u32 x, u32 y, u32 pad); 32 | void print_string_ext(const char *str, u16 fg_color, u16 bg_color, 33 | u32 x, u32 y, void *_dest_ptr, u32 pitch, u32 pad); 34 | void clear_screen(u16 color); 35 | void blit_to_screen(u16 *src, u32 w, u32 h, u32 x, u32 y); 36 | u16 *copy_screen(); 37 | void flip_screen(); 38 | void video_write_mem_savestate(file_tag_type savestate_file); 39 | void video_read_savestate(file_tag_type savestate_file); 40 | 41 | extern u32 frame_speed; 42 | 43 | extern s32 affine_reference_x[2]; 44 | extern s32 affine_reference_y[2]; 45 | 46 | typedef void (* tile_render_function)(u32 layer_number, u32 start, u32 end, 47 | void *dest_ptr); 48 | typedef void (* bitmap_render_function)(u32 start, u32 end, void *dest_ptr); 49 | 50 | typedef struct 51 | { 52 | tile_render_function normal_render_base; 53 | tile_render_function normal_render_transparent; 54 | tile_render_function alpha_render_base; 55 | tile_render_function alpha_render_transparent; 56 | tile_render_function color16_render_base; 57 | tile_render_function color16_render_transparent; 58 | tile_render_function color32_render_base; 59 | tile_render_function color32_render_transparent; 60 | } tile_layer_render_struct; 61 | 62 | typedef struct 63 | { 64 | bitmap_render_function normal_render; 65 | } bitmap_layer_render_struct; 66 | 67 | typedef enum 68 | { 69 | unscaled, 70 | scaled_aspect, 71 | fullscreen, 72 | } video_scale_type; 73 | 74 | typedef enum 75 | { 76 | filter_nearest, 77 | filter_bilinear 78 | } video_filter_type; 79 | 80 | extern video_scale_type screen_scale; 81 | extern video_scale_type current_scale; 82 | extern video_filter_type screen_filter; 83 | 84 | void set_gba_resolution(video_scale_type scale); 85 | void change_ext(u8 *src, u8 *buffer, u8 *extension); 86 | #endif 87 | -------------------------------------------------------------------------------- /x86/Makefile: -------------------------------------------------------------------------------- 1 | # gpSP makefile 2 | # Gilead Kutnick - Exophase 3 | 4 | # Global definitions 5 | 6 | CC = gcc 7 | STRIP = strip 8 | AS = as 9 | 10 | PREFIX = /usr 11 | OBJS = main.o cpu.o memory.o video.o input.o sound.o \ 12 | cpu_threaded.o gui.o x86_stub.o cheats.o zip.o 13 | BIN = gpsp.exe 14 | 15 | # Platform specific definitions 16 | 17 | VPATH += .. 18 | CFLAGS += 19 | INCLUDES = -I${PREFIX}/include `sdl-config --cflags` 20 | LIBS = -L${PREFIX}/lib `sdl-config --libs` -mconsole -lz 21 | 22 | # Compilation: 23 | 24 | .SUFFIXES: .c .S 25 | 26 | %.o: %.c 27 | ${CC} ${CFLAGS} ${INCLUDES} -c -o $@ $< 28 | 29 | %.o: %.S 30 | ${AS} -o $@ $< 31 | 32 | all: ${OBJS} 33 | ${CC} ${OBJS} ${LIBS} -o ${BIN} 34 | ${STRIP} ${BIN} 35 | 36 | clean: 37 | rm -f *.o ${BIN} 38 | 39 | -------------------------------------------------------------------------------- /x86/x86_stub.S: -------------------------------------------------------------------------------- 1 | # gameplaySP 2 | # 3 | # Copyright (C) 2006 Exophase 4 | # 5 | # This program is free software; you can redistribute it and/or 6 | # modify it under the terms of the GNU General Public License as 7 | # published by the Free Software Foundation; either version 2 of 8 | # the License, or (at your option) any later version. 9 | # 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | # General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with this program; if not, write to the Free Software 17 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 | 19 | .align 4 20 | 21 | .global _x86_update_gba 22 | .global _x86_indirect_branch_arm 23 | .global _x86_indirect_branch_thumb 24 | .global _x86_indirect_branch_dual 25 | .global _execute_store_u8 26 | .global _execute_store_u16 27 | .global _execute_store_u32 28 | .global _execute_arm_translate 29 | .global _step_debug_x86 30 | 31 | .global _memory_map_read 32 | .global _memory_map_write 33 | .global _reg 34 | 35 | .global _iwram 36 | .global _ewram 37 | .global _vram 38 | .global _bios_rom 39 | .global _io_registers 40 | 41 | .extern _spsr 42 | 43 | .equ REG_SP, (13 * 4) 44 | .equ REG_LR, (14 * 4) 45 | .equ REG_PC, (15 * 4) 46 | .equ REG_N_FLAG, (16 * 4) 47 | .equ REG_Z_FLAG, (17 * 4) 48 | .equ REG_C_FLAG, (18 * 4) 49 | .equ REG_V_FLAG, (19 * 4) 50 | .equ REG_CPSR, (20 * 4) 51 | .equ CPU_MODE, (29 * 4) 52 | .equ CPU_HALT_STATE, (30 * 4) 53 | .equ CHANGED_PC_STATUS, (31 * 4) 54 | 55 | # destroys ecx and edx 56 | 57 | .macro collapse_flag offset, shift 58 | mov _reg + \offset, %ecx 59 | shl $\shift, %ecx 60 | or %ecx, %edx 61 | .endm 62 | 63 | .macro collapse_flags 64 | xor %edx, %edx 65 | collapse_flag REG_N_FLAG, 31 66 | collapse_flag REG_Z_FLAG, 30 67 | collapse_flag REG_C_FLAG, 29 68 | collapse_flag REG_V_FLAG, 28 69 | mov REG_CPSR(%ebx), %ecx 70 | and $0xFF, %ecx 71 | or %ecx, %edx 72 | mov %edx, REG_CPSR(%ebx) 73 | .endm 74 | 75 | .macro extract_flag shift, offset 76 | mov REG_CPSR(%ebx), %edx 77 | shr $\shift, %edx 78 | and $0x01, %edx 79 | mov %edx, _reg + \offset 80 | .endm 81 | 82 | .macro extract_flags 83 | extract_flag 31, REG_N_FLAG 84 | extract_flag 30, REG_Z_FLAG 85 | extract_flag 29, REG_C_FLAG 86 | extract_flag 28, REG_V_FLAG 87 | .endm 88 | 89 | # Process a hardware event. Since an interrupt might be 90 | # raised we have to check if the PC has changed. 91 | 92 | # eax: current address 93 | 94 | _x86_update_gba: 95 | mov %eax, REG_PC(%ebx) # current PC = eax 96 | collapse_flags # update cpsr, trashes ecx and edx 97 | call _update_gba # process the next event 98 | 99 | mov %eax, %edi # edi = new cycle count 100 | # did the PC change? 101 | cmpl $1, CHANGED_PC_STATUS(%ebx) 102 | je lookup_pc 103 | ret # if not, go back to caller 104 | 105 | # Perform this on an indirect branch that will definitely go to 106 | # ARM code, IE anything that changes the PC in ARM mode except 107 | # for BX and data processing to PC with the S bit set. 108 | 109 | # eax: GBA address to branch to 110 | # edi: Cycle counter 111 | 112 | _x86_indirect_branch_arm: 113 | call _block_lookup_address_arm 114 | jmp *%eax 115 | 116 | # For indirect branches that'll definitely go to Thumb. In 117 | # Thumb mode any indirect branches except for BX. 118 | 119 | _x86_indirect_branch_thumb: 120 | call _block_lookup_address_thumb 121 | jmp *%eax 122 | 123 | # For indirect branches that can go to either Thumb or ARM, 124 | # mainly BX (also data processing to PC with S bit set, be 125 | # sure to adjust the target with a 1 in the lowest bit for this) 126 | 127 | _x86_indirect_branch_dual: 128 | call _block_lookup_address_dual 129 | jmp *%eax 130 | 131 | # eax: address to write to 132 | # edx: value to write 133 | # ecx: current pc 134 | 135 | .macro execute_store_ext_builder ext_function 136 | call \ext_function 137 | jmp write_epilogue 138 | .endm 139 | 140 | _execute_store_u8: 141 | mov %ecx, REG_PC(%ebx) # write out the PC 142 | mov %eax, %ecx # ecx = address 143 | test $0xF0000000, %ecx # check address range 144 | jnz ext_store_u8 # if above perform an extended write 145 | shr $15, %ecx # ecx = page number of address 146 | # load the corresponding memory map offset 147 | mov _memory_map_write(, %ecx, 4), %ecx 148 | test %ecx, %ecx # see if it's NULL 149 | jz ext_store_u8 # if so perform an extended write 150 | and $0x7FFF, %eax # isolate the lower 15bits of the address 151 | mov %dl, (%eax, %ecx) # store the value 152 | # check for self-modifying code 153 | testb $0xFF, -32768(%eax, %ecx) 154 | jne smc_write 155 | ret # return 156 | 157 | ext_store_u8: 158 | execute_store_ext_builder _write_memory8 159 | 160 | _execute_store_u16: 161 | mov %ecx, REG_PC(%ebx) # write out the PC 162 | and $~0x01, %eax # fix alignment 163 | mov %eax, %ecx # ecx = address 164 | test $0xF0000000, %ecx # check address range 165 | jnz ext_store_u16 # if above perform an extended write 166 | shr $15, %ecx # ecx = page number of address 167 | # load the corresponding memory map offset 168 | mov _memory_map_write(, %ecx, 4), %ecx 169 | test %ecx, %ecx # see if it's NULL 170 | jz ext_store_u16 # if so perform an extended write 171 | and $0x7FFF, %eax # isolate the lower 15bits of the address 172 | mov %dx, (%eax, %ecx) # store the value 173 | # check for self-modifying code 174 | testw $0xFFFF, -32768(%eax, %ecx) 175 | jne smc_write 176 | ret # return 177 | 178 | ext_store_u16: 179 | execute_store_ext_builder _write_memory16 180 | 181 | _execute_store_u32: 182 | mov %ecx, REG_PC(%ebx) # write out the PC 183 | and $~0x03, %eax # fix alignment 184 | mov %eax, %ecx # ecx = address 185 | test $0xF0000000, %ecx # check address range 186 | jnz ext_store_u32 # if above perform an extended write 187 | shr $15, %ecx # ecx = page number of address 188 | # load the corresponding memory map offset 189 | mov _memory_map_write(, %ecx, 4), %ecx 190 | test %ecx, %ecx # see if it's NULL 191 | jz ext_store_u32 # if so perform an extended write 192 | and $0x7FFF, %eax # isolate the lower 15bits of the address 193 | mov %edx, (%eax, %ecx) # store the value 194 | # check for self-modifying code 195 | testl $0xFFFFFFFF, -32768(%eax, %ecx) 196 | jne smc_write 197 | ret # return it 198 | 199 | ext_store_u32: 200 | execute_store_ext_builder _write_memory32 201 | 202 | write_epilogue: 203 | cmp $0, %eax # 0 return means nothing happened 204 | jz no_alert # if so we can leave 205 | 206 | collapse_flags # make sure flags are good for function call 207 | cmp $2, %eax # see if it was an SMC trigger 208 | je smc_write 209 | 210 | alert_loop: 211 | call _update_gba # process the next event 212 | # see if the halt status has changed 213 | mov CPU_HALT_STATE(%ebx), %edx 214 | 215 | cmp $0, %edx # 0 means it has 216 | jnz alert_loop # if not go again 217 | 218 | mov %eax, %edi # edi = new cycle count 219 | jmp lookup_pc # pc has definitely changed 220 | 221 | no_alert: 222 | ret 223 | 224 | # execute_store_epilogue_builder smc_thumb 225 | 226 | str: 227 | .asciz "looking up pc\n" 228 | 229 | smc_write: 230 | call _flush_translation_cache_ram 231 | 232 | lookup_pc: 233 | add $4, %esp 234 | movl $0, CHANGED_PC_STATUS(%ebx) 235 | mov REG_PC(%ebx), %eax 236 | testl $0x20, REG_CPSR(%ebx) 237 | jz lookup_pc_arm 238 | 239 | lookup_pc_thumb: 240 | call _block_lookup_address_thumb 241 | jmp *%eax 242 | 243 | lookup_pc_arm: 244 | call _block_lookup_address_arm 245 | jmp *%eax 246 | 247 | # eax: cycle counter 248 | 249 | _execute_arm_translate: 250 | movl $_reg, %ebx # load base register 251 | extract_flags # load flag variables 252 | movl %eax, %edi # load edi cycle counter 253 | 254 | movl REG_PC(%ebx), %eax # load PC 255 | call _block_lookup_address_arm 256 | jmp *%eax # jump to it 257 | 258 | _step_debug_x86: 259 | collapse_flags 260 | mov %edi, %edx 261 | jmp _step_debug 262 | 263 | .comm _memory_map_read 0x8000 264 | .comm _memory_map_write 0x8000 265 | .comm _reg 0x100 266 | 267 | 268 | -------------------------------------------------------------------------------- /zip.c: -------------------------------------------------------------------------------- 1 | /* gameplaySP 2 | * 3 | * Copyright (C) 2006 Exophase 4 | * Copyright (C) 2006 SiberianSTAR 5 | * 6 | * This program is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU General Public License as 8 | * published by the Free Software Foundation; either version 2 of 9 | * the License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | #include 22 | #include "common.h" 23 | 24 | #define ZIP_BUFFER_SIZE (128 * 1024) 25 | 26 | struct SZIPFileDataDescriptor 27 | { 28 | s32 CRC32; 29 | s32 CompressedSize; 30 | s32 UncompressedSize; 31 | } __attribute__((packed)); 32 | 33 | struct SZIPFileHeader 34 | { 35 | s32 Sig; 36 | s16 VersionToExtract; 37 | s16 GeneralBitFlag; 38 | s16 CompressionMethod; 39 | s16 LastModFileTime; 40 | s16 LastModFileDate; 41 | struct SZIPFileDataDescriptor DataDescriptor; 42 | s16 FilenameLength; 43 | s16 ExtraFieldLength; 44 | } __attribute__((packed)); 45 | 46 | u32 load_file_zip(char *filename) 47 | { 48 | struct SZIPFileHeader data; 49 | u8 tmp[1024]; 50 | s32 retval = -1; 51 | u8 *buffer = NULL; 52 | u8 *cbuffer; 53 | u8 *ext; 54 | 55 | file_open(fd, filename, read); 56 | 57 | if(!file_check_valid(fd)) 58 | return -1; 59 | 60 | while(1) 61 | { 62 | file_read(fd, &data, sizeof(struct SZIPFileHeader)); 63 | 64 | // zip file end 65 | if(data.Sig != 0x04034b50) 66 | break; 67 | 68 | file_read(fd, tmp, data.FilenameLength); 69 | tmp[data.FilenameLength] = 0; // end string 70 | 71 | if(data.ExtraFieldLength) 72 | file_seek(fd, data.ExtraFieldLength, SEEK_CUR); 73 | 74 | if(data.GeneralBitFlag & 0x0008) 75 | { 76 | file_read(fd, &data.DataDescriptor, 77 | sizeof(struct SZIPFileDataDescriptor)); 78 | } 79 | 80 | ext = strrchr(tmp, '.') + 1; 81 | 82 | // file is too big 83 | if(data.DataDescriptor.UncompressedSize > gamepak_ram_buffer_size) 84 | goto outcode; 85 | 86 | if(!strcasecmp(ext, "bin") || !strcasecmp(ext, "gba")) 87 | { 88 | buffer = gamepak_rom; 89 | 90 | // ok, found 91 | switch(data.CompressionMethod) 92 | { 93 | case 0: 94 | retval = data.DataDescriptor.UncompressedSize; 95 | file_read(fd, buffer, retval); 96 | 97 | goto outcode; 98 | 99 | case 8: 100 | { 101 | z_stream stream; 102 | s32 err; 103 | 104 | cbuffer = malloc(ZIP_BUFFER_SIZE); 105 | 106 | stream.next_in = (Bytef*)cbuffer; 107 | stream.avail_in = (u32)ZIP_BUFFER_SIZE; 108 | 109 | stream.next_out = (Bytef*)buffer; 110 | retval = stream.avail_out = data.DataDescriptor.UncompressedSize; 111 | 112 | stream.zalloc = (alloc_func)0; 113 | stream.zfree = (free_func)0; 114 | 115 | err = inflateInit2(&stream, -MAX_WBITS); 116 | 117 | file_read(fd, cbuffer, ZIP_BUFFER_SIZE); 118 | 119 | if(err == Z_OK) 120 | { 121 | while(err != Z_STREAM_END) 122 | { 123 | err = inflate(&stream, Z_SYNC_FLUSH); 124 | if(err == Z_BUF_ERROR) 125 | { 126 | stream.avail_in = ZIP_BUFFER_SIZE; 127 | stream.next_in = (Bytef*)cbuffer; 128 | file_read(fd, cbuffer, ZIP_BUFFER_SIZE); 129 | } 130 | } 131 | err = Z_OK; 132 | inflateEnd(&stream); 133 | } 134 | free(cbuffer); 135 | goto outcode; 136 | } 137 | } 138 | } 139 | } 140 | 141 | outcode: 142 | file_close(fd); 143 | 144 | return retval; 145 | } 146 | -------------------------------------------------------------------------------- /zip.h: -------------------------------------------------------------------------------- 1 | /* gameplaySP 2 | * 3 | * Copyright (C) 2006 Exophase 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License as 7 | * published by the Free Software Foundation; either version 2 of 8 | * the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #ifndef COMMON_H 21 | #define COMMON_H 22 | 23 | u32 load_file_zip(char *filename); 24 | 25 | #endif 26 | 27 | --------------------------------------------------------------------------------