Mercurial > vba-clojure
changeset 17:75e5bb1e0aa1
going to now integrate the gb src tree since it has no dependencies
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Mar 2012 11:44:47 -0600 |
parents | 9e598342e182 |
children | ac56489c2ca6 |
files | src/gb/GB.cpp src/gb/GB.h src/gb/Makefile.am src/gb/gbCheats.cpp src/gb/gbCheats.h src/gb/gbCodes.h src/gb/gbCodesCB.h src/gb/gbDis.cpp src/gb/gbGfx.cpp src/gb/gbGlobals.cpp src/gb/gbGlobals.h src/gb/gbMemory.cpp src/gb/gbMemory.h src/gb/gbPrinter.cpp src/gb/gbPrinter.h src/gb/gbSGB.cpp src/gb/gbSGB.h src/gb/gbSound.cpp src/gb/gbSound.h |
diffstat | 19 files changed, 11765 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/gb/GB.cpp Sat Mar 03 11:44:47 2012 -0600 1.3 @@ -0,0 +1,3918 @@ 1.4 +#include <cstdio> 1.5 +#include <cstdlib> 1.6 +#include <cstring> 1.7 +#include <cassert> 1.8 + 1.9 +#include "../Port.h" 1.10 +#include "../NLS.h" 1.11 +#include "GB.h" 1.12 +#include "gbCheats.h" 1.13 +#include "gbGlobals.h" 1.14 +#include "gbMemory.h" 1.15 +#include "gbSGB.h" 1.16 +#include "gbSound.h" 1.17 +#include "../common/unzip.h" 1.18 +#include "../common/Util.h" 1.19 +#include "../common/System.h" 1.20 +#include "../common/movie.h" 1.21 +#include "../common/vbalua.h" 1.22 + 1.23 +#ifdef __GNUC__ 1.24 +#define _stricmp strcasecmp 1.25 +#endif 1.26 + 1.27 +// FIXME: constant (GB) or boolean (GBA)?! 1.28 +#define C_FLAG 0x10 1.29 +#define H_FLAG 0x20 1.30 +#define N_FLAG 0x40 1.31 +#define Z_FLAG 0x80 1.32 +extern soundtick_t GB_USE_TICKS_AS; 1.33 + 1.34 +u8 * origPix = NULL; 1.35 +extern u8 * pix; 1.36 +extern u32 extButtons; 1.37 +extern bool8 capturePrevious; 1.38 +extern int32 captureNumber; 1.39 +extern bool8 speedup; 1.40 + 1.41 +bool gbUpdateSizes(); 1.42 + 1.43 +// debugging 1.44 +bool memorydebug = false; 1.45 +char gbBuffer[2048]; 1.46 + 1.47 +extern u16 gbLineMix[160]; 1.48 + 1.49 +// mappers 1.50 +void (*mapper)(u16, u8) = NULL; 1.51 +void (*mapperRAM)(u16, u8) = NULL; 1.52 +u8 (*mapperReadRAM)(u16) = NULL; 1.53 + 1.54 +// registers 1.55 +gbRegister PC; 1.56 +gbRegister SP; 1.57 +gbRegister AF; 1.58 +gbRegister BC; 1.59 +gbRegister DE; 1.60 +gbRegister HL; 1.61 +u16 IFF; 1.62 +// 0xff04 1.63 +u8 register_DIV = 0; 1.64 +// 0xff05 1.65 +u8 register_TIMA = 0; 1.66 +// 0xff06 1.67 +u8 register_TMA = 0; 1.68 +// 0xff07 1.69 +u8 register_TAC = 0; 1.70 +// 0xff0f 1.71 +u8 register_IF = 0; 1.72 +// 0xff40 1.73 +u8 register_LCDC = 0; 1.74 +// 0xff41 1.75 +u8 register_STAT = 0; 1.76 +// 0xff42 1.77 +u8 register_SCY = 0; 1.78 +// 0xff43 1.79 +u8 register_SCX = 0; 1.80 +// 0xff44 1.81 +u8 register_LY = 0; 1.82 +// 0xff45 1.83 +u8 register_LYC = 0; 1.84 +// 0xff46 1.85 +u8 register_DMA = 0; 1.86 +// 0xff4a 1.87 +u8 register_WY = 0; 1.88 +// 0xff4b 1.89 +u8 register_WX = 0; 1.90 +// 0xff4f 1.91 +u8 register_VBK = 0; 1.92 +// 0xff51 1.93 +u8 register_HDMA1 = 0; 1.94 +// 0xff52 1.95 +u8 register_HDMA2 = 0; 1.96 +// 0xff53 1.97 +u8 register_HDMA3 = 0; 1.98 +// 0xff54 1.99 +u8 register_HDMA4 = 0; 1.100 +// 0xff55 1.101 +u8 register_HDMA5 = 0; 1.102 +// 0xff70 1.103 +u8 register_SVBK = 0; 1.104 +// 0xffff 1.105 +u8 register_IE = 0; 1.106 + 1.107 +// ticks definition 1.108 +int32 GBDIV_CLOCK_TICKS = 64; 1.109 +int32 GBLCD_MODE_0_CLOCK_TICKS = 51; 1.110 +int32 GBLCD_MODE_1_CLOCK_TICKS = 1140; 1.111 +int32 GBLCD_MODE_2_CLOCK_TICKS = 20; 1.112 +int32 GBLCD_MODE_3_CLOCK_TICKS = 43; 1.113 +int32 GBLY_INCREMENT_CLOCK_TICKS = 114; 1.114 +int32 GBTIMER_MODE_0_CLOCK_TICKS = 256; 1.115 +int32 GBTIMER_MODE_1_CLOCK_TICKS = 4; 1.116 +int32 GBTIMER_MODE_2_CLOCK_TICKS = 16; 1.117 +int32 GBTIMER_MODE_3_CLOCK_TICKS = 64; 1.118 +int32 GBSERIAL_CLOCK_TICKS = 128; 1.119 +int32 GBSYNCHRONIZE_CLOCK_TICKS = 52920; 1.120 + 1.121 +// state variables 1.122 + 1.123 +// interrupt 1.124 +int32 gbInterrupt = 0; 1.125 +int32 gbInterruptWait = 0; 1.126 +// serial 1.127 +int32 gbSerialOn = 0; 1.128 +int32 gbSerialTicks = 0; 1.129 +int32 gbSerialBits = 0; 1.130 +// timer 1.131 +int32 gbTimerOn = 0; 1.132 +int32 gbTimerTicks = 0; 1.133 +int32 gbTimerClockTicks = 0; 1.134 +int32 gbTimerMode = 0; 1.135 +// lcd 1.136 +int32 gbLcdMode = 2; 1.137 +int32 gbLcdTicks = GBLCD_MODE_2_CLOCK_TICKS; 1.138 +int32 gbLcdLYIncrementTicks = 0; 1.139 +// div 1.140 +int32 gbDivTicks = GBDIV_CLOCK_TICKS; 1.141 +// cgb 1.142 +int32 gbVramBank = 0; 1.143 +int32 gbWramBank = 1; 1.144 +int32 gbHdmaSource = 0x0000; 1.145 +int32 gbHdmaDestination = 0x8000; 1.146 +int32 gbHdmaBytes = 0x0000; 1.147 +int32 gbHdmaOn = 0; 1.148 +int32 gbSpeed = 0; 1.149 +// frame counting 1.150 +int32 gbFrameCount = 0; 1.151 +int32 gbFrameSkip = 0; 1.152 +int32 gbFrameSkipCount = 0; 1.153 +// timing 1.154 +u32 gbLastTime = 0; 1.155 +u32 gbElapsedTime = 0; 1.156 +u32 gbTimeNow = 0; 1.157 +int32 gbSynchronizeTicks = GBSYNCHRONIZE_CLOCK_TICKS; 1.158 +int32 gbDMASpeedVersion = 1; 1.159 +// emulator features 1.160 +int32 gbBattery = 0; 1.161 +int32 gbJoymask[4] = { 0, 0, 0, 0 }; 1.162 + 1.163 +int32 gbEchoRAMFixOn = 1; 1.164 + 1.165 +static bool newFrame = true; 1.166 +static bool pauseAfterFrameAdvance = false; 1.167 + 1.168 +int32 gbRomSizes[] = { 0x00008000, // 32K 1.169 + 0x00010000, // 64K 1.170 + 0x00020000, // 128K 1.171 + 0x00040000, // 256K 1.172 + 0x00080000, // 512K 1.173 + 0x00100000, // 1024K 1.174 + 0x00200000, // 2048K 1.175 + 0x00400000, // 4096K 1.176 + 0x00800000 // 8192K 1.177 +}; 1.178 +int32 gbRomSizesMasks[] = { 0x00007fff, 1.179 + 0x0000ffff, 1.180 + 0x0001ffff, 1.181 + 0x0003ffff, 1.182 + 0x0007ffff, 1.183 + 0x000fffff, 1.184 + 0x001fffff, 1.185 + 0x003fffff, 1.186 + 0x007fffff }; 1.187 + 1.188 +int32 gbRamSizes[6] = { 0x00000000, // 0K 1.189 + 0x00000800, // 2K 1.190 + 0x00002000, // 8K 1.191 + 0x00008000, // 32K 1.192 + 0x00020000, // 128K 1.193 + 0x00010000 // 64K 1.194 +}; 1.195 + 1.196 +int32 gbRamSizesMasks[6] = { 0x00000000, 1.197 + 0x000007ff, 1.198 + 0x00001fff, 1.199 + 0x00007fff, 1.200 + 0x0001ffff, 1.201 + 0x0000ffff }; 1.202 + 1.203 +int32 gbCycles[] = 1.204 +{ 1.205 +// 0 1 2 3 4 5 6 7 8 9 a b c d e f 1.206 + 1, 3, 2, 2, 1, 1, 2, 1, 5, 2, 2, 2, 1, 1, 2, 1, // 0 1.207 + 1, 3, 2, 2, 1, 1, 2, 1, 3, 2, 2, 2, 1, 1, 2, 1, // 1 1.208 + 2, 3, 2, 2, 1, 1, 2, 1, 2, 2, 2, 2, 1, 1, 2, 1, // 2 1.209 + 2, 3, 2, 2, 3, 3, 3, 1, 2, 2, 2, 2, 1, 1, 2, 1, // 3 1.210 + 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, // 4 1.211 + 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, // 5 1.212 + 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, // 6 1.213 + 2, 2, 2, 2, 2, 2, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1, // 7 1.214 + 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, // 8 1.215 + 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, // 9 1.216 + 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, // a 1.217 + 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, // b 1.218 + 2, 3, 3, 4, 3, 4, 2, 4, 2, 4, 3, 2, 3, 6, 2, 4, // c 1.219 + 2, 3, 3, 0, 3, 4, 2, 4, 2, 4, 3, 0, 3, 0, 2, 4, // d 1.220 + 3, 3, 2, 0, 0, 4, 2, 4, 4, 1, 4, 0, 0, 0, 2, 4, // e 1.221 + 3, 3, 2, 1, 0, 4, 2, 4, 3, 2, 4, 1, 0, 0, 2, 4 // f 1.222 +}; 1.223 + 1.224 +int32 gbCyclesCB[] = 1.225 +{ 1.226 +// 0 1 2 3 4 5 6 7 8 9 a b c d e f 1.227 + 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, // 0 1.228 + 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, // 1 1.229 + 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, // 2 1.230 + 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, // 3 1.231 + 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // 4 1.232 + 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // 5 1.233 + 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // 6 1.234 + 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // 7 1.235 + 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // 8 1.236 + 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // 9 1.237 + 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // a 1.238 + 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // b 1.239 + 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // c 1.240 + 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // d 1.241 + 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // e 1.242 + 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2 // f 1.243 +}; 1.244 + 1.245 +u16 DAATable[] = 1.246 +{ 1.247 + 0x0080, 0x0100, 0x0200, 0x0300, 0x0400, 0x0500, 0x0600, 0x0700, 1.248 + 0x0800, 0x0900, 0x1020, 0x1120, 0x1220, 0x1320, 0x1420, 0x1520, 1.249 + 0x1000, 0x1100, 0x1200, 0x1300, 0x1400, 0x1500, 0x1600, 0x1700, 1.250 + 0x1800, 0x1900, 0x2020, 0x2120, 0x2220, 0x2320, 0x2420, 0x2520, 1.251 + 0x2000, 0x2100, 0x2200, 0x2300, 0x2400, 0x2500, 0x2600, 0x2700, 1.252 + 0x2800, 0x2900, 0x3020, 0x3120, 0x3220, 0x3320, 0x3420, 0x3520, 1.253 + 0x3000, 0x3100, 0x3200, 0x3300, 0x3400, 0x3500, 0x3600, 0x3700, 1.254 + 0x3800, 0x3900, 0x4020, 0x4120, 0x4220, 0x4320, 0x4420, 0x4520, 1.255 + 0x4000, 0x4100, 0x4200, 0x4300, 0x4400, 0x4500, 0x4600, 0x4700, 1.256 + 0x4800, 0x4900, 0x5020, 0x5120, 0x5220, 0x5320, 0x5420, 0x5520, 1.257 + 0x5000, 0x5100, 0x5200, 0x5300, 0x5400, 0x5500, 0x5600, 0x5700, 1.258 + 0x5800, 0x5900, 0x6020, 0x6120, 0x6220, 0x6320, 0x6420, 0x6520, 1.259 + 0x6000, 0x6100, 0x6200, 0x6300, 0x6400, 0x6500, 0x6600, 0x6700, 1.260 + 0x6800, 0x6900, 0x7020, 0x7120, 0x7220, 0x7320, 0x7420, 0x7520, 1.261 + 0x7000, 0x7100, 0x7200, 0x7300, 0x7400, 0x7500, 0x7600, 0x7700, 1.262 + 0x7800, 0x7900, 0x8020, 0x8120, 0x8220, 0x8320, 0x8420, 0x8520, 1.263 + 0x8000, 0x8100, 0x8200, 0x8300, 0x8400, 0x8500, 0x8600, 0x8700, 1.264 + 0x8800, 0x8900, 0x9020, 0x9120, 0x9220, 0x9320, 0x9420, 0x9520, 1.265 + 0x9000, 0x9100, 0x9200, 0x9300, 0x9400, 0x9500, 0x9600, 0x9700, 1.266 + 0x9800, 0x9900, 0x00B0, 0x0130, 0x0230, 0x0330, 0x0430, 0x0530, 1.267 + 0x0090, 0x0110, 0x0210, 0x0310, 0x0410, 0x0510, 0x0610, 0x0710, 1.268 + 0x0810, 0x0910, 0x1030, 0x1130, 0x1230, 0x1330, 0x1430, 0x1530, 1.269 + 0x1010, 0x1110, 0x1210, 0x1310, 0x1410, 0x1510, 0x1610, 0x1710, 1.270 + 0x1810, 0x1910, 0x2030, 0x2130, 0x2230, 0x2330, 0x2430, 0x2530, 1.271 + 0x2010, 0x2110, 0x2210, 0x2310, 0x2410, 0x2510, 0x2610, 0x2710, 1.272 + 0x2810, 0x2910, 0x3030, 0x3130, 0x3230, 0x3330, 0x3430, 0x3530, 1.273 + 0x3010, 0x3110, 0x3210, 0x3310, 0x3410, 0x3510, 0x3610, 0x3710, 1.274 + 0x3810, 0x3910, 0x4030, 0x4130, 0x4230, 0x4330, 0x4430, 0x4530, 1.275 + 0x4010, 0x4110, 0x4210, 0x4310, 0x4410, 0x4510, 0x4610, 0x4710, 1.276 + 0x4810, 0x4910, 0x5030, 0x5130, 0x5230, 0x5330, 0x5430, 0x5530, 1.277 + 0x5010, 0x5110, 0x5210, 0x5310, 0x5410, 0x5510, 0x5610, 0x5710, 1.278 + 0x5810, 0x5910, 0x6030, 0x6130, 0x6230, 0x6330, 0x6430, 0x6530, 1.279 + 0x6010, 0x6110, 0x6210, 0x6310, 0x6410, 0x6510, 0x6610, 0x6710, 1.280 + 0x6810, 0x6910, 0x7030, 0x7130, 0x7230, 0x7330, 0x7430, 0x7530, 1.281 + 0x7010, 0x7110, 0x7210, 0x7310, 0x7410, 0x7510, 0x7610, 0x7710, 1.282 + 0x7810, 0x7910, 0x8030, 0x8130, 0x8230, 0x8330, 0x8430, 0x8530, 1.283 + 0x8010, 0x8110, 0x8210, 0x8310, 0x8410, 0x8510, 0x8610, 0x8710, 1.284 + 0x8810, 0x8910, 0x9030, 0x9130, 0x9230, 0x9330, 0x9430, 0x9530, 1.285 + 0x9010, 0x9110, 0x9210, 0x9310, 0x9410, 0x9510, 0x9610, 0x9710, 1.286 + 0x9810, 0x9910, 0xA030, 0xA130, 0xA230, 0xA330, 0xA430, 0xA530, 1.287 + 0xA010, 0xA110, 0xA210, 0xA310, 0xA410, 0xA510, 0xA610, 0xA710, 1.288 + 0xA810, 0xA910, 0xB030, 0xB130, 0xB230, 0xB330, 0xB430, 0xB530, 1.289 + 0xB010, 0xB110, 0xB210, 0xB310, 0xB410, 0xB510, 0xB610, 0xB710, 1.290 + 0xB810, 0xB910, 0xC030, 0xC130, 0xC230, 0xC330, 0xC430, 0xC530, 1.291 + 0xC010, 0xC110, 0xC210, 0xC310, 0xC410, 0xC510, 0xC610, 0xC710, 1.292 + 0xC810, 0xC910, 0xD030, 0xD130, 0xD230, 0xD330, 0xD430, 0xD530, 1.293 + 0xD010, 0xD110, 0xD210, 0xD310, 0xD410, 0xD510, 0xD610, 0xD710, 1.294 + 0xD810, 0xD910, 0xE030, 0xE130, 0xE230, 0xE330, 0xE430, 0xE530, 1.295 + 0xE010, 0xE110, 0xE210, 0xE310, 0xE410, 0xE510, 0xE610, 0xE710, 1.296 + 0xE810, 0xE910, 0xF030, 0xF130, 0xF230, 0xF330, 0xF430, 0xF530, 1.297 + 0xF010, 0xF110, 0xF210, 0xF310, 0xF410, 0xF510, 0xF610, 0xF710, 1.298 + 0xF810, 0xF910, 0x00B0, 0x0130, 0x0230, 0x0330, 0x0430, 0x0530, 1.299 + 0x0090, 0x0110, 0x0210, 0x0310, 0x0410, 0x0510, 0x0610, 0x0710, 1.300 + 0x0810, 0x0910, 0x1030, 0x1130, 0x1230, 0x1330, 0x1430, 0x1530, 1.301 + 0x1010, 0x1110, 0x1210, 0x1310, 0x1410, 0x1510, 0x1610, 0x1710, 1.302 + 0x1810, 0x1910, 0x2030, 0x2130, 0x2230, 0x2330, 0x2430, 0x2530, 1.303 + 0x2010, 0x2110, 0x2210, 0x2310, 0x2410, 0x2510, 0x2610, 0x2710, 1.304 + 0x2810, 0x2910, 0x3030, 0x3130, 0x3230, 0x3330, 0x3430, 0x3530, 1.305 + 0x3010, 0x3110, 0x3210, 0x3310, 0x3410, 0x3510, 0x3610, 0x3710, 1.306 + 0x3810, 0x3910, 0x4030, 0x4130, 0x4230, 0x4330, 0x4430, 0x4530, 1.307 + 0x4010, 0x4110, 0x4210, 0x4310, 0x4410, 0x4510, 0x4610, 0x4710, 1.308 + 0x4810, 0x4910, 0x5030, 0x5130, 0x5230, 0x5330, 0x5430, 0x5530, 1.309 + 0x5010, 0x5110, 0x5210, 0x5310, 0x5410, 0x5510, 0x5610, 0x5710, 1.310 + 0x5810, 0x5910, 0x6030, 0x6130, 0x6230, 0x6330, 0x6430, 0x6530, 1.311 + 0x0600, 0x0700, 0x0800, 0x0900, 0x0A00, 0x0B00, 0x0C00, 0x0D00, 1.312 + 0x0E00, 0x0F00, 0x1020, 0x1120, 0x1220, 0x1320, 0x1420, 0x1520, 1.313 + 0x1600, 0x1700, 0x1800, 0x1900, 0x1A00, 0x1B00, 0x1C00, 0x1D00, 1.314 + 0x1E00, 0x1F00, 0x2020, 0x2120, 0x2220, 0x2320, 0x2420, 0x2520, 1.315 + 0x2600, 0x2700, 0x2800, 0x2900, 0x2A00, 0x2B00, 0x2C00, 0x2D00, 1.316 + 0x2E00, 0x2F00, 0x3020, 0x3120, 0x3220, 0x3320, 0x3420, 0x3520, 1.317 + 0x3600, 0x3700, 0x3800, 0x3900, 0x3A00, 0x3B00, 0x3C00, 0x3D00, 1.318 + 0x3E00, 0x3F00, 0x4020, 0x4120, 0x4220, 0x4320, 0x4420, 0x4520, 1.319 + 0x4600, 0x4700, 0x4800, 0x4900, 0x4A00, 0x4B00, 0x4C00, 0x4D00, 1.320 + 0x4E00, 0x4F00, 0x5020, 0x5120, 0x5220, 0x5320, 0x5420, 0x5520, 1.321 + 0x5600, 0x5700, 0x5800, 0x5900, 0x5A00, 0x5B00, 0x5C00, 0x5D00, 1.322 + 0x5E00, 0x5F00, 0x6020, 0x6120, 0x6220, 0x6320, 0x6420, 0x6520, 1.323 + 0x6600, 0x6700, 0x6800, 0x6900, 0x6A00, 0x6B00, 0x6C00, 0x6D00, 1.324 + 0x6E00, 0x6F00, 0x7020, 0x7120, 0x7220, 0x7320, 0x7420, 0x7520, 1.325 + 0x7600, 0x7700, 0x7800, 0x7900, 0x7A00, 0x7B00, 0x7C00, 0x7D00, 1.326 + 0x7E00, 0x7F00, 0x8020, 0x8120, 0x8220, 0x8320, 0x8420, 0x8520, 1.327 + 0x8600, 0x8700, 0x8800, 0x8900, 0x8A00, 0x8B00, 0x8C00, 0x8D00, 1.328 + 0x8E00, 0x8F00, 0x9020, 0x9120, 0x9220, 0x9320, 0x9420, 0x9520, 1.329 + 0x9600, 0x9700, 0x9800, 0x9900, 0x9A00, 0x9B00, 0x9C00, 0x9D00, 1.330 + 0x9E00, 0x9F00, 0x00B0, 0x0130, 0x0230, 0x0330, 0x0430, 0x0530, 1.331 + 0x0610, 0x0710, 0x0810, 0x0910, 0x0A10, 0x0B10, 0x0C10, 0x0D10, 1.332 + 0x0E10, 0x0F10, 0x1030, 0x1130, 0x1230, 0x1330, 0x1430, 0x1530, 1.333 + 0x1610, 0x1710, 0x1810, 0x1910, 0x1A10, 0x1B10, 0x1C10, 0x1D10, 1.334 + 0x1E10, 0x1F10, 0x2030, 0x2130, 0x2230, 0x2330, 0x2430, 0x2530, 1.335 + 0x2610, 0x2710, 0x2810, 0x2910, 0x2A10, 0x2B10, 0x2C10, 0x2D10, 1.336 + 0x2E10, 0x2F10, 0x3030, 0x3130, 0x3230, 0x3330, 0x3430, 0x3530, 1.337 + 0x3610, 0x3710, 0x3810, 0x3910, 0x3A10, 0x3B10, 0x3C10, 0x3D10, 1.338 + 0x3E10, 0x3F10, 0x4030, 0x4130, 0x4230, 0x4330, 0x4430, 0x4530, 1.339 + 0x4610, 0x4710, 0x4810, 0x4910, 0x4A10, 0x4B10, 0x4C10, 0x4D10, 1.340 + 0x4E10, 0x4F10, 0x5030, 0x5130, 0x5230, 0x5330, 0x5430, 0x5530, 1.341 + 0x5610, 0x5710, 0x5810, 0x5910, 0x5A10, 0x5B10, 0x5C10, 0x5D10, 1.342 + 0x5E10, 0x5F10, 0x6030, 0x6130, 0x6230, 0x6330, 0x6430, 0x6530, 1.343 + 0x6610, 0x6710, 0x6810, 0x6910, 0x6A10, 0x6B10, 0x6C10, 0x6D10, 1.344 + 0x6E10, 0x6F10, 0x7030, 0x7130, 0x7230, 0x7330, 0x7430, 0x7530, 1.345 + 0x7610, 0x7710, 0x7810, 0x7910, 0x7A10, 0x7B10, 0x7C10, 0x7D10, 1.346 + 0x7E10, 0x7F10, 0x8030, 0x8130, 0x8230, 0x8330, 0x8430, 0x8530, 1.347 + 0x8610, 0x8710, 0x8810, 0x8910, 0x8A10, 0x8B10, 0x8C10, 0x8D10, 1.348 + 0x8E10, 0x8F10, 0x9030, 0x9130, 0x9230, 0x9330, 0x9430, 0x9530, 1.349 + 0x9610, 0x9710, 0x9810, 0x9910, 0x9A10, 0x9B10, 0x9C10, 0x9D10, 1.350 + 0x9E10, 0x9F10, 0xA030, 0xA130, 0xA230, 0xA330, 0xA430, 0xA530, 1.351 + 0xA610, 0xA710, 0xA810, 0xA910, 0xAA10, 0xAB10, 0xAC10, 0xAD10, 1.352 + 0xAE10, 0xAF10, 0xB030, 0xB130, 0xB230, 0xB330, 0xB430, 0xB530, 1.353 + 0xB610, 0xB710, 0xB810, 0xB910, 0xBA10, 0xBB10, 0xBC10, 0xBD10, 1.354 + 0xBE10, 0xBF10, 0xC030, 0xC130, 0xC230, 0xC330, 0xC430, 0xC530, 1.355 + 0xC610, 0xC710, 0xC810, 0xC910, 0xCA10, 0xCB10, 0xCC10, 0xCD10, 1.356 + 0xCE10, 0xCF10, 0xD030, 0xD130, 0xD230, 0xD330, 0xD430, 0xD530, 1.357 + 0xD610, 0xD710, 0xD810, 0xD910, 0xDA10, 0xDB10, 0xDC10, 0xDD10, 1.358 + 0xDE10, 0xDF10, 0xE030, 0xE130, 0xE230, 0xE330, 0xE430, 0xE530, 1.359 + 0xE610, 0xE710, 0xE810, 0xE910, 0xEA10, 0xEB10, 0xEC10, 0xED10, 1.360 + 0xEE10, 0xEF10, 0xF030, 0xF130, 0xF230, 0xF330, 0xF430, 0xF530, 1.361 + 0xF610, 0xF710, 0xF810, 0xF910, 0xFA10, 0xFB10, 0xFC10, 0xFD10, 1.362 + 0xFE10, 0xFF10, 0x00B0, 0x0130, 0x0230, 0x0330, 0x0430, 0x0530, 1.363 + 0x0610, 0x0710, 0x0810, 0x0910, 0x0A10, 0x0B10, 0x0C10, 0x0D10, 1.364 + 0x0E10, 0x0F10, 0x1030, 0x1130, 0x1230, 0x1330, 0x1430, 0x1530, 1.365 + 0x1610, 0x1710, 0x1810, 0x1910, 0x1A10, 0x1B10, 0x1C10, 0x1D10, 1.366 + 0x1E10, 0x1F10, 0x2030, 0x2130, 0x2230, 0x2330, 0x2430, 0x2530, 1.367 + 0x2610, 0x2710, 0x2810, 0x2910, 0x2A10, 0x2B10, 0x2C10, 0x2D10, 1.368 + 0x2E10, 0x2F10, 0x3030, 0x3130, 0x3230, 0x3330, 0x3430, 0x3530, 1.369 + 0x3610, 0x3710, 0x3810, 0x3910, 0x3A10, 0x3B10, 0x3C10, 0x3D10, 1.370 + 0x3E10, 0x3F10, 0x4030, 0x4130, 0x4230, 0x4330, 0x4430, 0x4530, 1.371 + 0x4610, 0x4710, 0x4810, 0x4910, 0x4A10, 0x4B10, 0x4C10, 0x4D10, 1.372 + 0x4E10, 0x4F10, 0x5030, 0x5130, 0x5230, 0x5330, 0x5430, 0x5530, 1.373 + 0x5610, 0x5710, 0x5810, 0x5910, 0x5A10, 0x5B10, 0x5C10, 0x5D10, 1.374 + 0x5E10, 0x5F10, 0x6030, 0x6130, 0x6230, 0x6330, 0x6430, 0x6530, 1.375 + 0x00C0, 0x0140, 0x0240, 0x0340, 0x0440, 0x0540, 0x0640, 0x0740, 1.376 + 0x0840, 0x0940, 0x0440, 0x0540, 0x0640, 0x0740, 0x0840, 0x0940, 1.377 + 0x1040, 0x1140, 0x1240, 0x1340, 0x1440, 0x1540, 0x1640, 0x1740, 1.378 + 0x1840, 0x1940, 0x1440, 0x1540, 0x1640, 0x1740, 0x1840, 0x1940, 1.379 + 0x2040, 0x2140, 0x2240, 0x2340, 0x2440, 0x2540, 0x2640, 0x2740, 1.380 + 0x2840, 0x2940, 0x2440, 0x2540, 0x2640, 0x2740, 0x2840, 0x2940, 1.381 + 0x3040, 0x3140, 0x3240, 0x3340, 0x3440, 0x3540, 0x3640, 0x3740, 1.382 + 0x3840, 0x3940, 0x3440, 0x3540, 0x3640, 0x3740, 0x3840, 0x3940, 1.383 + 0x4040, 0x4140, 0x4240, 0x4340, 0x4440, 0x4540, 0x4640, 0x4740, 1.384 + 0x4840, 0x4940, 0x4440, 0x4540, 0x4640, 0x4740, 0x4840, 0x4940, 1.385 + 0x5040, 0x5140, 0x5240, 0x5340, 0x5440, 0x5540, 0x5640, 0x5740, 1.386 + 0x5840, 0x5940, 0x5440, 0x5540, 0x5640, 0x5740, 0x5840, 0x5940, 1.387 + 0x6040, 0x6140, 0x6240, 0x6340, 0x6440, 0x6540, 0x6640, 0x6740, 1.388 + 0x6840, 0x6940, 0x6440, 0x6540, 0x6640, 0x6740, 0x6840, 0x6940, 1.389 + 0x7040, 0x7140, 0x7240, 0x7340, 0x7440, 0x7540, 0x7640, 0x7740, 1.390 + 0x7840, 0x7940, 0x7440, 0x7540, 0x7640, 0x7740, 0x7840, 0x7940, 1.391 + 0x8040, 0x8140, 0x8240, 0x8340, 0x8440, 0x8540, 0x8640, 0x8740, 1.392 + 0x8840, 0x8940, 0x8440, 0x8540, 0x8640, 0x8740, 0x8840, 0x8940, 1.393 + 0x9040, 0x9140, 0x9240, 0x9340, 0x9440, 0x9540, 0x9640, 0x9740, 1.394 + 0x9840, 0x9940, 0x3450, 0x3550, 0x3650, 0x3750, 0x3850, 0x3950, 1.395 + 0x4050, 0x4150, 0x4250, 0x4350, 0x4450, 0x4550, 0x4650, 0x4750, 1.396 + 0x4850, 0x4950, 0x4450, 0x4550, 0x4650, 0x4750, 0x4850, 0x4950, 1.397 + 0x5050, 0x5150, 0x5250, 0x5350, 0x5450, 0x5550, 0x5650, 0x5750, 1.398 + 0x5850, 0x5950, 0x5450, 0x5550, 0x5650, 0x5750, 0x5850, 0x5950, 1.399 + 0x6050, 0x6150, 0x6250, 0x6350, 0x6450, 0x6550, 0x6650, 0x6750, 1.400 + 0x6850, 0x6950, 0x6450, 0x6550, 0x6650, 0x6750, 0x6850, 0x6950, 1.401 + 0x7050, 0x7150, 0x7250, 0x7350, 0x7450, 0x7550, 0x7650, 0x7750, 1.402 + 0x7850, 0x7950, 0x7450, 0x7550, 0x7650, 0x7750, 0x7850, 0x7950, 1.403 + 0x8050, 0x8150, 0x8250, 0x8350, 0x8450, 0x8550, 0x8650, 0x8750, 1.404 + 0x8850, 0x8950, 0x8450, 0x8550, 0x8650, 0x8750, 0x8850, 0x8950, 1.405 + 0x9050, 0x9150, 0x9250, 0x9350, 0x9450, 0x9550, 0x9650, 0x9750, 1.406 + 0x9850, 0x9950, 0x9450, 0x9550, 0x9650, 0x9750, 0x9850, 0x9950, 1.407 + 0xA050, 0xA150, 0xA250, 0xA350, 0xA450, 0xA550, 0xA650, 0xA750, 1.408 + 0xA850, 0xA950, 0xA450, 0xA550, 0xA650, 0xA750, 0xA850, 0xA950, 1.409 + 0xB050, 0xB150, 0xB250, 0xB350, 0xB450, 0xB550, 0xB650, 0xB750, 1.410 + 0xB850, 0xB950, 0xB450, 0xB550, 0xB650, 0xB750, 0xB850, 0xB950, 1.411 + 0xC050, 0xC150, 0xC250, 0xC350, 0xC450, 0xC550, 0xC650, 0xC750, 1.412 + 0xC850, 0xC950, 0xC450, 0xC550, 0xC650, 0xC750, 0xC850, 0xC950, 1.413 + 0xD050, 0xD150, 0xD250, 0xD350, 0xD450, 0xD550, 0xD650, 0xD750, 1.414 + 0xD850, 0xD950, 0xD450, 0xD550, 0xD650, 0xD750, 0xD850, 0xD950, 1.415 + 0xE050, 0xE150, 0xE250, 0xE350, 0xE450, 0xE550, 0xE650, 0xE750, 1.416 + 0xE850, 0xE950, 0xE450, 0xE550, 0xE650, 0xE750, 0xE850, 0xE950, 1.417 + 0xF050, 0xF150, 0xF250, 0xF350, 0xF450, 0xF550, 0xF650, 0xF750, 1.418 + 0xF850, 0xF950, 0xF450, 0xF550, 0xF650, 0xF750, 0xF850, 0xF950, 1.419 + 0x00D0, 0x0150, 0x0250, 0x0350, 0x0450, 0x0550, 0x0650, 0x0750, 1.420 + 0x0850, 0x0950, 0x0450, 0x0550, 0x0650, 0x0750, 0x0850, 0x0950, 1.421 + 0x1050, 0x1150, 0x1250, 0x1350, 0x1450, 0x1550, 0x1650, 0x1750, 1.422 + 0x1850, 0x1950, 0x1450, 0x1550, 0x1650, 0x1750, 0x1850, 0x1950, 1.423 + 0x2050, 0x2150, 0x2250, 0x2350, 0x2450, 0x2550, 0x2650, 0x2750, 1.424 + 0x2850, 0x2950, 0x2450, 0x2550, 0x2650, 0x2750, 0x2850, 0x2950, 1.425 + 0x3050, 0x3150, 0x3250, 0x3350, 0x3450, 0x3550, 0x3650, 0x3750, 1.426 + 0x3850, 0x3950, 0x3450, 0x3550, 0x3650, 0x3750, 0x3850, 0x3950, 1.427 + 0x4050, 0x4150, 0x4250, 0x4350, 0x4450, 0x4550, 0x4650, 0x4750, 1.428 + 0x4850, 0x4950, 0x4450, 0x4550, 0x4650, 0x4750, 0x4850, 0x4950, 1.429 + 0x5050, 0x5150, 0x5250, 0x5350, 0x5450, 0x5550, 0x5650, 0x5750, 1.430 + 0x5850, 0x5950, 0x5450, 0x5550, 0x5650, 0x5750, 0x5850, 0x5950, 1.431 + 0x6050, 0x6150, 0x6250, 0x6350, 0x6450, 0x6550, 0x6650, 0x6750, 1.432 + 0x6850, 0x6950, 0x6450, 0x6550, 0x6650, 0x6750, 0x6850, 0x6950, 1.433 + 0x7050, 0x7150, 0x7250, 0x7350, 0x7450, 0x7550, 0x7650, 0x7750, 1.434 + 0x7850, 0x7950, 0x7450, 0x7550, 0x7650, 0x7750, 0x7850, 0x7950, 1.435 + 0x8050, 0x8150, 0x8250, 0x8350, 0x8450, 0x8550, 0x8650, 0x8750, 1.436 + 0x8850, 0x8950, 0x8450, 0x8550, 0x8650, 0x8750, 0x8850, 0x8950, 1.437 + 0x9050, 0x9150, 0x9250, 0x9350, 0x9450, 0x9550, 0x9650, 0x9750, 1.438 + 0x9850, 0x9950, 0x9450, 0x9550, 0x9650, 0x9750, 0x9850, 0x9950, 1.439 + 0xFA60, 0xFB60, 0xFC60, 0xFD60, 0xFE60, 0xFF60, 0x00C0, 0x0140, 1.440 + 0x0240, 0x0340, 0x0440, 0x0540, 0x0640, 0x0740, 0x0840, 0x0940, 1.441 + 0x0A60, 0x0B60, 0x0C60, 0x0D60, 0x0E60, 0x0F60, 0x1040, 0x1140, 1.442 + 0x1240, 0x1340, 0x1440, 0x1540, 0x1640, 0x1740, 0x1840, 0x1940, 1.443 + 0x1A60, 0x1B60, 0x1C60, 0x1D60, 0x1E60, 0x1F60, 0x2040, 0x2140, 1.444 + 0x2240, 0x2340, 0x2440, 0x2540, 0x2640, 0x2740, 0x2840, 0x2940, 1.445 + 0x2A60, 0x2B60, 0x2C60, 0x2D60, 0x2E60, 0x2F60, 0x3040, 0x3140, 1.446 + 0x3240, 0x3340, 0x3440, 0x3540, 0x3640, 0x3740, 0x3840, 0x3940, 1.447 + 0x3A60, 0x3B60, 0x3C60, 0x3D60, 0x3E60, 0x3F60, 0x4040, 0x4140, 1.448 + 0x4240, 0x4340, 0x4440, 0x4540, 0x4640, 0x4740, 0x4840, 0x4940, 1.449 + 0x4A60, 0x4B60, 0x4C60, 0x4D60, 0x4E60, 0x4F60, 0x5040, 0x5140, 1.450 + 0x5240, 0x5340, 0x5440, 0x5540, 0x5640, 0x5740, 0x5840, 0x5940, 1.451 + 0x5A60, 0x5B60, 0x5C60, 0x5D60, 0x5E60, 0x5F60, 0x6040, 0x6140, 1.452 + 0x6240, 0x6340, 0x6440, 0x6540, 0x6640, 0x6740, 0x6840, 0x6940, 1.453 + 0x6A60, 0x6B60, 0x6C60, 0x6D60, 0x6E60, 0x6F60, 0x7040, 0x7140, 1.454 + 0x7240, 0x7340, 0x7440, 0x7540, 0x7640, 0x7740, 0x7840, 0x7940, 1.455 + 0x7A60, 0x7B60, 0x7C60, 0x7D60, 0x7E60, 0x7F60, 0x8040, 0x8140, 1.456 + 0x8240, 0x8340, 0x8440, 0x8540, 0x8640, 0x8740, 0x8840, 0x8940, 1.457 + 0x8A60, 0x8B60, 0x8C60, 0x8D60, 0x8E60, 0x8F60, 0x9040, 0x9140, 1.458 + 0x9240, 0x9340, 0x3450, 0x3550, 0x3650, 0x3750, 0x3850, 0x3950, 1.459 + 0x3A70, 0x3B70, 0x3C70, 0x3D70, 0x3E70, 0x3F70, 0x4050, 0x4150, 1.460 + 0x4250, 0x4350, 0x4450, 0x4550, 0x4650, 0x4750, 0x4850, 0x4950, 1.461 + 0x4A70, 0x4B70, 0x4C70, 0x4D70, 0x4E70, 0x4F70, 0x5050, 0x5150, 1.462 + 0x5250, 0x5350, 0x5450, 0x5550, 0x5650, 0x5750, 0x5850, 0x5950, 1.463 + 0x5A70, 0x5B70, 0x5C70, 0x5D70, 0x5E70, 0x5F70, 0x6050, 0x6150, 1.464 + 0x6250, 0x6350, 0x6450, 0x6550, 0x6650, 0x6750, 0x6850, 0x6950, 1.465 + 0x6A70, 0x6B70, 0x6C70, 0x6D70, 0x6E70, 0x6F70, 0x7050, 0x7150, 1.466 + 0x7250, 0x7350, 0x7450, 0x7550, 0x7650, 0x7750, 0x7850, 0x7950, 1.467 + 0x7A70, 0x7B70, 0x7C70, 0x7D70, 0x7E70, 0x7F70, 0x8050, 0x8150, 1.468 + 0x8250, 0x8350, 0x8450, 0x8550, 0x8650, 0x8750, 0x8850, 0x8950, 1.469 + 0x8A70, 0x8B70, 0x8C70, 0x8D70, 0x8E70, 0x8F70, 0x9050, 0x9150, 1.470 + 0x9250, 0x9350, 0x9450, 0x9550, 0x9650, 0x9750, 0x9850, 0x9950, 1.471 + 0x9A70, 0x9B70, 0x9C70, 0x9D70, 0x9E70, 0x9F70, 0xA050, 0xA150, 1.472 + 0xA250, 0xA350, 0xA450, 0xA550, 0xA650, 0xA750, 0xA850, 0xA950, 1.473 + 0xAA70, 0xAB70, 0xAC70, 0xAD70, 0xAE70, 0xAF70, 0xB050, 0xB150, 1.474 + 0xB250, 0xB350, 0xB450, 0xB550, 0xB650, 0xB750, 0xB850, 0xB950, 1.475 + 0xBA70, 0xBB70, 0xBC70, 0xBD70, 0xBE70, 0xBF70, 0xC050, 0xC150, 1.476 + 0xC250, 0xC350, 0xC450, 0xC550, 0xC650, 0xC750, 0xC850, 0xC950, 1.477 + 0xCA70, 0xCB70, 0xCC70, 0xCD70, 0xCE70, 0xCF70, 0xD050, 0xD150, 1.478 + 0xD250, 0xD350, 0xD450, 0xD550, 0xD650, 0xD750, 0xD850, 0xD950, 1.479 + 0xDA70, 0xDB70, 0xDC70, 0xDD70, 0xDE70, 0xDF70, 0xE050, 0xE150, 1.480 + 0xE250, 0xE350, 0xE450, 0xE550, 0xE650, 0xE750, 0xE850, 0xE950, 1.481 + 0xEA70, 0xEB70, 0xEC70, 0xED70, 0xEE70, 0xEF70, 0xF050, 0xF150, 1.482 + 0xF250, 0xF350, 0xF450, 0xF550, 0xF650, 0xF750, 0xF850, 0xF950, 1.483 + 0xFA70, 0xFB70, 0xFC70, 0xFD70, 0xFE70, 0xFF70, 0x00D0, 0x0150, 1.484 + 0x0250, 0x0350, 0x0450, 0x0550, 0x0650, 0x0750, 0x0850, 0x0950, 1.485 + 0x0A70, 0x0B70, 0x0C70, 0x0D70, 0x0E70, 0x0F70, 0x1050, 0x1150, 1.486 + 0x1250, 0x1350, 0x1450, 0x1550, 0x1650, 0x1750, 0x1850, 0x1950, 1.487 + 0x1A70, 0x1B70, 0x1C70, 0x1D70, 0x1E70, 0x1F70, 0x2050, 0x2150, 1.488 + 0x2250, 0x2350, 0x2450, 0x2550, 0x2650, 0x2750, 0x2850, 0x2950, 1.489 + 0x2A70, 0x2B70, 0x2C70, 0x2D70, 0x2E70, 0x2F70, 0x3050, 0x3150, 1.490 + 0x3250, 0x3350, 0x3450, 0x3550, 0x3650, 0x3750, 0x3850, 0x3950, 1.491 + 0x3A70, 0x3B70, 0x3C70, 0x3D70, 0x3E70, 0x3F70, 0x4050, 0x4150, 1.492 + 0x4250, 0x4350, 0x4450, 0x4550, 0x4650, 0x4750, 0x4850, 0x4950, 1.493 + 0x4A70, 0x4B70, 0x4C70, 0x4D70, 0x4E70, 0x4F70, 0x5050, 0x5150, 1.494 + 0x5250, 0x5350, 0x5450, 0x5550, 0x5650, 0x5750, 0x5850, 0x5950, 1.495 + 0x5A70, 0x5B70, 0x5C70, 0x5D70, 0x5E70, 0x5F70, 0x6050, 0x6150, 1.496 + 0x6250, 0x6350, 0x6450, 0x6550, 0x6650, 0x6750, 0x6850, 0x6950, 1.497 + 0x6A70, 0x6B70, 0x6C70, 0x6D70, 0x6E70, 0x6F70, 0x7050, 0x7150, 1.498 + 0x7250, 0x7350, 0x7450, 0x7550, 0x7650, 0x7750, 0x7850, 0x7950, 1.499 + 0x7A70, 0x7B70, 0x7C70, 0x7D70, 0x7E70, 0x7F70, 0x8050, 0x8150, 1.500 + 0x8250, 0x8350, 0x8450, 0x8550, 0x8650, 0x8750, 0x8850, 0x8950, 1.501 + 0x8A70, 0x8B70, 0x8C70, 0x8D70, 0x8E70, 0x8F70, 0x9050, 0x9150, 1.502 + 0x9250, 0x9350, 0x9450, 0x9550, 0x9650, 0x9750, 0x9850, 0x9950, 1.503 +}; 1.504 + 1.505 +u8 ZeroTable[] = 1.506 +{ 1.507 + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.508 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.509 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.510 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.511 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.512 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.513 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.514 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.515 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.516 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.517 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.518 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.519 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.520 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.521 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.522 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 1.523 +}; 1.524 + 1.525 +#define GBSAVE_GAME_VERSION_1 1 1.526 +#define GBSAVE_GAME_VERSION_2 2 1.527 +#define GBSAVE_GAME_VERSION_3 3 1.528 +#define GBSAVE_GAME_VERSION_4 4 1.529 +#define GBSAVE_GAME_VERSION_5 5 1.530 +#define GBSAVE_GAME_VERSION_6 6 1.531 +#define GBSAVE_GAME_VERSION_7 7 1.532 +#define GBSAVE_GAME_VERSION_8 8 1.533 +#define GBSAVE_GAME_VERSION_9 9 1.534 +#define GBSAVE_GAME_VERSION_10 10 1.535 +#define GBSAVE_GAME_VERSION_11 11 1.536 +#define GBSAVE_GAME_VERSION_12 12 1.537 +#define GBSAVE_GAME_VERSION_13 13 1.538 +#define GBSAVE_GAME_VERSION GBSAVE_GAME_VERSION_13 1.539 + 1.540 +int inline gbGetValue(int min, int max, int v) 1.541 +{ 1.542 + return (int)(min + (float)(max - min) * (2.0 * (v / 31.0) - (v / 31.0) * (v / 31.0))); 1.543 +} 1.544 + 1.545 +void gbGenFilter() 1.546 +{ 1.547 + for (int r = 0; r < 32; r++) 1.548 + { 1.549 + for (int g = 0; g < 32; g++) 1.550 + { 1.551 + for (int b = 0; b < 32; b++) 1.552 + { 1.553 + int nr = gbGetValue(gbGetValue(4, 14, g), 1.554 + gbGetValue(24, 29, g), r) - 4; 1.555 + int ng = gbGetValue(gbGetValue(4 + gbGetValue(0, 5, r), 1.556 + 14 + gbGetValue(0, 3, r), b), 1.557 + gbGetValue(24 + gbGetValue(0, 3, r), 1.558 + 29 + gbGetValue(0, 1, r), b), g) - 4; 1.559 + int nb = gbGetValue(gbGetValue(4 + gbGetValue(0, 5, r), 1.560 + 14 + gbGetValue(0, 3, r), g), 1.561 + gbGetValue(24 + gbGetValue(0, 3, r), 1.562 + 29 + gbGetValue(0, 1, r), g), b) - 4; 1.563 + gbColorFilter[(b << 10) | (g << 5) | r] = (nb << 10) | (ng << 5) | nr; 1.564 + } 1.565 + } 1.566 + } 1.567 +} 1.568 + 1.569 +void gbCopyMemory(u16 d, u16 s, int count) 1.570 +{ 1.571 + while (count) 1.572 + { 1.573 + gbWriteMemoryQuick(d, gbReadMemoryQuick(s)); 1.574 + s++; 1.575 + d++; 1.576 + count--; 1.577 + } 1.578 +} 1.579 + 1.580 +void gbDoHdma() 1.581 +{ 1.582 + gbCopyMemory(gbHdmaDestination, gbHdmaSource, 0x10); 1.583 + 1.584 + gbHdmaDestination += 0x10; 1.585 + gbHdmaSource += 0x10; 1.586 + 1.587 + register_HDMA2 = (register_HDMA2 + 0x10) & 0xFF; 1.588 + if (register_HDMA2 == 0x00) 1.589 + register_HDMA1++; 1.590 + 1.591 + register_HDMA4 = (register_HDMA4 + 0x10) & 0xFF; 1.592 + if (register_HDMA4 == 0x00) 1.593 + register_HDMA3++; 1.594 + 1.595 + if (gbHdmaDestination == 0x96b0) 1.596 + gbHdmaBytes = gbHdmaBytes; 1.597 + gbHdmaBytes -= 0x10; 1.598 + register_HDMA5--; 1.599 + if (register_HDMA5 == 0xff) 1.600 + gbHdmaOn = 0; 1.601 +} 1.602 + 1.603 +// fix for Harley and Lego Racers 1.604 +void gbCompareLYToLYC() 1.605 +{ 1.606 + if (register_LY == register_LYC) 1.607 + { 1.608 + // mark that we have a match 1.609 + register_STAT |= 4; 1.610 + 1.611 + // check if we need an interrupt 1.612 + if ((register_STAT & 0x40) && (register_IE & 2)) 1.613 + gbInterrupt |= 2; 1.614 + } 1.615 + else // no match 1.616 + register_STAT &= 0xfb; 1.617 +} 1.618 + 1.619 +// FIXME: horrible kludge to workaround the frame timing bug 1.620 +static int32 s_gbJoymask[4] = { 0, 0, 0, 0 }; 1.621 + 1.622 +void gbWriteMemoryWrapped(register u16 address, register u8 value) 1.623 +{ 1.624 + if (address < 0x8000) 1.625 + { 1.626 +#ifndef FINAL_VERSION 1.627 + if (memorydebug && (address > 0x3fff || address < 0x2000)) 1.628 + { 1.629 + log("Memory register write %04x=%02x PC=%04x\n", 1.630 + address, 1.631 + value, 1.632 + PC.W); 1.633 + } 1.634 +#endif 1.635 + if (mapper) 1.636 + (*mapper)(address, value); 1.637 + return; 1.638 + } 1.639 + 1.640 + if (address < 0xa000) 1.641 + { 1.642 + gbWriteMemoryQuick(address, value); 1.643 + return; 1.644 + } 1.645 + 1.646 + if (address < 0xc000) 1.647 + { 1.648 +#ifndef FINAL_VERSION 1.649 + if (memorydebug) 1.650 + { 1.651 + log("Memory register write %04x=%02x PC=%04x\n", 1.652 + address, 1.653 + value, 1.654 + PC.W); 1.655 + } 1.656 +#endif 1.657 + 1.658 + if (mapper) 1.659 + (*mapperRAM)(address, value); 1.660 + return; 1.661 + } 1.662 + 1.663 + if (address < 0xfe00) 1.664 + { 1.665 + gbWriteMemoryQuick(address, value); 1.666 + return; 1.667 + } 1.668 + 1.669 + if (address < 0xff00) 1.670 + { 1.671 + gbMemory[address] = value; 1.672 + return; 1.673 + } 1.674 + 1.675 + switch (address & 0x00ff) 1.676 + { 1.677 + case 0x00: 1.678 + { 1.679 + gbMemory[0xff00] = ((gbMemory[0xff00] & 0xcf) | 1.680 + (value & 0x30)); 1.681 + if (gbSgbMode) 1.682 + { 1.683 + gbSgbDoBitTransfer(value); 1.684 + } 1.685 + 1.686 + return; 1.687 + } 1.688 + 1.689 + case 0x01: 1.690 + { 1.691 + gbMemory[0xff01] = value; 1.692 + return; 1.693 + } 1.694 + 1.695 + // serial control 1.696 + case 0x02: 1.697 + { 1.698 + gbSerialOn = (value & 0x80); 1.699 + gbMemory[0xff02] = value; 1.700 + if (gbSerialOn) 1.701 + { 1.702 + gbSerialTicks = GBSERIAL_CLOCK_TICKS; 1.703 +#ifdef LINK_EMULATION 1.704 + if (linkConnected) 1.705 + { 1.706 + if (value & 1) 1.707 + { 1.708 + linkSendByte(0x100 | gbMemory[0xFF01]); 1.709 + Sleep(5); 1.710 + } 1.711 + } 1.712 +#endif 1.713 + } 1.714 + 1.715 + gbSerialBits = 0; 1.716 + return; 1.717 + } 1.718 + 1.719 + // DIV register resets on any write 1.720 + case 0x04: 1.721 + { 1.722 + register_DIV = 0; 1.723 + return; 1.724 + } 1.725 + case 0x05: 1.726 + register_TIMA = value; 1.727 + return; 1.728 + 1.729 + case 0x06: 1.730 + register_TMA = value; 1.731 + return; 1.732 + 1.733 + // TIMER control 1.734 + case 0x07: 1.735 + { 1.736 + register_TAC = value; 1.737 + 1.738 + gbTimerOn = (value & 4); 1.739 + gbTimerMode = value & 3; 1.740 + // register_TIMA = register_TMA; 1.741 + switch (gbTimerMode) 1.742 + { 1.743 + case 0: 1.744 + gbTimerClockTicks = gbTimerTicks = GBTIMER_MODE_0_CLOCK_TICKS; 1.745 + break; 1.746 + case 1: 1.747 + gbTimerClockTicks = gbTimerTicks = GBTIMER_MODE_1_CLOCK_TICKS; 1.748 + break; 1.749 + case 2: 1.750 + gbTimerClockTicks = gbTimerTicks = GBTIMER_MODE_2_CLOCK_TICKS; 1.751 + break; 1.752 + case 3: 1.753 + gbTimerClockTicks = gbTimerTicks = GBTIMER_MODE_3_CLOCK_TICKS; 1.754 + break; 1.755 + } 1.756 + return; 1.757 + } 1.758 + 1.759 + case 0x0f: 1.760 + { 1.761 + register_IF = value; 1.762 + gbInterrupt = value; 1.763 + return; 1.764 + } 1.765 + 1.766 + case 0x10: 1.767 + case 0x11: 1.768 + case 0x12: 1.769 + case 0x13: 1.770 + case 0x14: 1.771 + case 0x15: 1.772 + case 0x16: 1.773 + case 0x17: 1.774 + case 0x18: 1.775 + case 0x19: 1.776 + case 0x1a: 1.777 + case 0x1b: 1.778 + case 0x1c: 1.779 + case 0x1d: 1.780 + case 0x1e: 1.781 + case 0x1f: 1.782 + case 0x20: 1.783 + case 0x21: 1.784 + case 0x22: 1.785 + case 0x23: 1.786 + case 0x24: 1.787 + case 0x25: 1.788 + case 0x26: 1.789 + { 1.790 + SOUND_EVENT(address, value); 1.791 + return; 1.792 + } 1.793 + case 0x40: 1.794 + { 1.795 + int lcdChange = (register_LCDC & 0x80) ^ (value & 0x80); 1.796 + 1.797 + if (lcdChange) 1.798 + { 1.799 + if (value & 0x80) 1.800 + { 1.801 + gbLcdTicks = GBLCD_MODE_1_CLOCK_TICKS; 1.802 + gbLcdMode = 0; 1.803 + register_STAT &= 0xfc; 1.804 + register_LY = 0x00; 1.805 + // FIXME: horrible workaround 1.806 + if (gbNullInputHackTempEnabled && !useOldFrameTiming) 1.807 + memcpy(gbJoymask, s_gbJoymask, sizeof(gbJoymask)); 1.808 + } 1.809 + else 1.810 + { 1.811 + gbLcdTicks = 0; 1.812 + gbLcdMode = 0; 1.813 + register_STAT &= 0xfc; 1.814 + register_LY = 0x00; 1.815 + // FIXME: horrible workaround 1.816 + memcpy(s_gbJoymask, gbJoymask, sizeof(gbJoymask)); 1.817 + if (gbNullInputHackTempEnabled && !useOldFrameTiming) 1.818 + memset(gbJoymask, 0, sizeof(gbJoymask)); 1.819 + } 1.820 + // compareLYToLYC(); 1.821 + } 1.822 + // don't draw the window if it was not enabled and not being drawn before 1.823 + if (!(register_LCDC & 0x20) && (value & 0x20) && gbWindowLine == -1 && 1.824 + register_LY > register_WY) 1.825 + gbWindowLine = 144; 1.826 + 1.827 + register_LCDC = value; 1.828 + 1.829 + return; 1.830 + } 1.831 + 1.832 + // STAT 1.833 + case 0x41: 1.834 + { 1.835 + //register_STAT = (register_STAT & 0x87) | 1.836 + // (value & 0x7c); 1.837 + register_STAT = (value & 0xf8) | (register_STAT & 0x07); // fix ? 1.838 + // GB bug from Devrs FAQ 1.839 + if (!gbCgbMode && (register_LCDC & 0x80) && gbLcdMode < 2) 1.840 + gbInterrupt |= 2; 1.841 + return; 1.842 + } 1.843 + 1.844 + // SCY 1.845 + case 0x42: 1.846 + { 1.847 + register_SCY = value; 1.848 + return; 1.849 + } 1.850 + 1.851 + // SCX 1.852 + case 0x43: 1.853 + { 1.854 + register_SCX = value; 1.855 + return; 1.856 + } 1.857 + 1.858 + // LY 1.859 + case 0x44: 1.860 + { 1.861 + // read only 1.862 + return; 1.863 + } 1.864 + 1.865 + // LYC 1.866 + case 0x45: 1.867 + { 1.868 + register_LYC = value; 1.869 + if ((register_LCDC & 0x80)) 1.870 + { 1.871 + gbCompareLYToLYC(); 1.872 + } 1.873 + return; 1.874 + } 1.875 + 1.876 + // DMA! 1.877 + case 0x46: 1.878 + { 1.879 + int source = value * 0x0100; 1.880 + 1.881 + gbCopyMemory(0xfe00, 1.882 + source, 1.883 + 0xa0); 1.884 + register_DMA = value; 1.885 + return; 1.886 + } 1.887 + 1.888 + // BGP 1.889 + case 0x47: 1.890 + { 1.891 + gbBgp[0] = value & 0x03; 1.892 + gbBgp[1] = (value & 0x0c) >> 2; 1.893 + gbBgp[2] = (value & 0x30) >> 4; 1.894 + gbBgp[3] = (value & 0xc0) >> 6; 1.895 + break; 1.896 + } 1.897 + 1.898 + // OBP0 1.899 + case 0x48: 1.900 + { 1.901 + gbObp0[0] = value & 0x03; 1.902 + gbObp0[1] = (value & 0x0c) >> 2; 1.903 + gbObp0[2] = (value & 0x30) >> 4; 1.904 + gbObp0[3] = (value & 0xc0) >> 6; 1.905 + break; 1.906 + } 1.907 + 1.908 + // OBP1 1.909 + case 0x49: 1.910 + { 1.911 + gbObp1[0] = value & 0x03; 1.912 + gbObp1[1] = (value & 0x0c) >> 2; 1.913 + gbObp1[2] = (value & 0x30) >> 4; 1.914 + gbObp1[3] = (value & 0xc0) >> 6; 1.915 + break; 1.916 + } 1.917 + 1.918 + case 0x4a: 1.919 + register_WY = value; 1.920 + return; 1.921 + 1.922 + case 0x4b: 1.923 + register_WX = value; 1.924 + return; 1.925 + 1.926 + // KEY1 1.927 + case 0x4d: 1.928 + { 1.929 + if (gbCgbMode) 1.930 + { 1.931 + gbMemory[0xff4d] = (gbMemory[0xff4d] & 0x80) | (value & 1); 1.932 + return; 1.933 + } 1.934 + break; 1.935 + } 1.936 + 1.937 + // VBK 1.938 + case 0x4f: 1.939 + { 1.940 + if (gbCgbMode) 1.941 + { 1.942 + value = value & 1; 1.943 + if (value == gbVramBank) 1.944 + return; 1.945 + 1.946 + int vramAddress = value * 0x2000; 1.947 + gbMemoryMap[0x08] = &gbVram[vramAddress]; 1.948 + gbMemoryMap[0x09] = &gbVram[vramAddress + 0x1000]; 1.949 + 1.950 + gbVramBank = value; 1.951 + register_VBK = value; 1.952 + } 1.953 + return; 1.954 + break; 1.955 + } 1.956 + 1.957 + // HDMA1 1.958 + case 0x51: 1.959 + { 1.960 + if (gbCgbMode) 1.961 + { 1.962 + if (value > 0x7f && value < 0xa0) 1.963 + value = 0; 1.964 + 1.965 + gbHdmaSource = (value << 8) | (register_HDMA2 & 0xf0); 1.966 + 1.967 + register_HDMA1 = value; 1.968 + return; 1.969 + } 1.970 + break; 1.971 + } 1.972 + 1.973 + // HDMA2 1.974 + case 0x52: 1.975 + { 1.976 + if (gbCgbMode) 1.977 + { 1.978 + value = value & 0xf0; 1.979 + 1.980 + gbHdmaSource = (register_HDMA1 << 8) | (value); 1.981 + 1.982 + register_HDMA2 = value; 1.983 + return; 1.984 + } 1.985 + break; 1.986 + } 1.987 + 1.988 + // HDMA3 1.989 + case 0x53: 1.990 + { 1.991 + if (gbCgbMode) 1.992 + { 1.993 + value = value & 0x1f; 1.994 + gbHdmaDestination = (value << 8) | (register_HDMA4 & 0xf0); 1.995 + gbHdmaDestination += 0x8000; 1.996 + register_HDMA3 = value; 1.997 + return; 1.998 + } 1.999 + break; 1.1000 + } 1.1001 + 1.1002 + // HDMA4 1.1003 + case 0x54: 1.1004 + { 1.1005 + if (gbCgbMode) 1.1006 + { 1.1007 + value = value & 0xf0; 1.1008 + gbHdmaDestination = ((register_HDMA3 & 0x1f) << 8) | value; 1.1009 + gbHdmaDestination += 0x8000; 1.1010 + register_HDMA4 = value; 1.1011 + return; 1.1012 + } 1.1013 + break; 1.1014 + } 1.1015 + 1.1016 + // HDMA5 1.1017 + case 0x55: 1.1018 + { 1.1019 + if (gbCgbMode) 1.1020 + { 1.1021 + gbHdmaBytes = 16 + (value & 0x7f) * 16; 1.1022 + if (gbHdmaOn) 1.1023 + { 1.1024 + if (value & 0x80) 1.1025 + { 1.1026 + register_HDMA5 = (value & 0x7f); 1.1027 + } 1.1028 + else 1.1029 + { 1.1030 + register_HDMA5 = 0xff; 1.1031 + gbHdmaOn = 0; 1.1032 + } 1.1033 + } 1.1034 + else 1.1035 + { 1.1036 + if (value & 0x80) 1.1037 + { 1.1038 + gbHdmaOn = 1; 1.1039 + register_HDMA5 = value & 0x7f; 1.1040 + if (gbLcdMode == 0) 1.1041 + gbDoHdma(); 1.1042 + } 1.1043 + else 1.1044 + { 1.1045 + // we need to take the time it takes to complete the transfer into 1.1046 + // account... according to GB DEV FAQs, the setup time is the same 1.1047 + // for single and double speed, but the actual transfer takes the 1.1048 + // same time // (is that a typo?) 1.1049 + switch (gbDMASpeedVersion) 1.1050 + { 1.1051 + case 1: // I believe this is more correct 1.1052 + // the lower 7 bits of FF55 specify the Transfer Length (divided by 16, minus 1) 1.1053 + // and we make gbDmaTicks twice as many cycles at double speed to make the transfer take the same time 1.1054 + if (gbSpeed) 1.1055 + gbDmaTicks = 16 * ((value & 0x7f) + 1); 1.1056 + else 1.1057 + gbDmaTicks = 8 * ((value & 0x7f) + 1); 1.1058 + break; 1.1059 + case 0: // here for backward compatibility 1.1060 + // I think this was a guess that approximates the above in most but not all games 1.1061 + if (gbSpeed) 1.1062 + gbDmaTicks = 231 + 16 * (value & 0x7f); 1.1063 + else 1.1064 + gbDmaTicks = 231 + 8 * (value & 0x7f); 1.1065 + break; 1.1066 + default: // shouldn't happen 1.1067 + //assert(0); 1.1068 + break; 1.1069 + } 1.1070 + gbCopyMemory(gbHdmaDestination, gbHdmaSource, gbHdmaBytes); 1.1071 + gbHdmaDestination += gbHdmaBytes; 1.1072 + gbHdmaSource += gbHdmaBytes; 1.1073 + 1.1074 + register_HDMA3 = ((gbHdmaDestination - 0x8000) >> 8) & 0x1f; 1.1075 + register_HDMA4 = gbHdmaDestination & 0xf0; 1.1076 + register_HDMA1 = (gbHdmaSource >> 8) & 0xff; 1.1077 + register_HDMA2 = gbHdmaSource & 0xf0; 1.1078 + } 1.1079 + } 1.1080 + return; 1.1081 + } 1.1082 + break; 1.1083 + } 1.1084 + 1.1085 + // BCPS 1.1086 + case 0x68: 1.1087 + { 1.1088 + if (gbCgbMode) 1.1089 + { 1.1090 + int paletteIndex = (value & 0x3f) >> 1; 1.1091 + int paletteHiLo = (value & 0x01); 1.1092 + 1.1093 + gbMemory[0xff68] = value; 1.1094 + gbMemory[0xff69] = (paletteHiLo ? 1.1095 + (gbPalette[paletteIndex] >> 8) : 1.1096 + (gbPalette[paletteIndex] & 0x00ff)); 1.1097 + return; 1.1098 + } 1.1099 + break; 1.1100 + } 1.1101 + 1.1102 + // BCPD 1.1103 + case 0x69: 1.1104 + { 1.1105 + if (gbCgbMode) 1.1106 + { 1.1107 + int v = gbMemory[0xff68]; 1.1108 + int paletteIndex = (v & 0x3f) >> 1; 1.1109 + int paletteHiLo = (v & 0x01); 1.1110 + gbMemory[0xff69] = value; 1.1111 + gbPalette[paletteIndex] = (paletteHiLo ? 1.1112 + ((value << 8) | (gbPalette[paletteIndex] & 0xff)) : 1.1113 + ((gbPalette[paletteIndex] & 0xff00) | (value))) & 0x7fff; 1.1114 + 1.1115 + if (gbMemory[0xff68] & 0x80) 1.1116 + { 1.1117 + int index = ((gbMemory[0xff68] & 0x3f) + 1) & 0x3f; 1.1118 + 1.1119 + gbMemory[0xff68] = (gbMemory[0xff68] & 0x80) | index; 1.1120 + 1.1121 + gbMemory[0xff69] = (index & 1 ? 1.1122 + (gbPalette[index >> 1] >> 8) : 1.1123 + (gbPalette[index >> 1] & 0x00ff)); 1.1124 + } 1.1125 + return; 1.1126 + } 1.1127 + break; 1.1128 + } 1.1129 + 1.1130 + // OCPS 1.1131 + case 0x6a: 1.1132 + { 1.1133 + if (gbCgbMode) 1.1134 + { 1.1135 + int paletteIndex = (value & 0x3f) >> 1; 1.1136 + int paletteHiLo = (value & 0x01); 1.1137 + 1.1138 + paletteIndex += 32; 1.1139 + 1.1140 + gbMemory[0xff6a] = value; 1.1141 + gbMemory[0xff6b] = (paletteHiLo ? 1.1142 + (gbPalette[paletteIndex] >> 8) : 1.1143 + (gbPalette[paletteIndex] & 0x00ff)); 1.1144 + return; 1.1145 + } 1.1146 + break; 1.1147 + } 1.1148 + 1.1149 + // OCPD 1.1150 + case 0x6b: 1.1151 + { 1.1152 + if (gbCgbMode) 1.1153 + { 1.1154 + int v = gbMemory[0xff6a]; 1.1155 + int paletteIndex = (v & 0x3f) >> 1; 1.1156 + int paletteHiLo = (v & 0x01); 1.1157 + 1.1158 + paletteIndex += 32; 1.1159 + 1.1160 + gbMemory[0xff6b] = value; 1.1161 + gbPalette[paletteIndex] = (paletteHiLo ? 1.1162 + ((value << 8) | (gbPalette[paletteIndex] & 0xff)) : 1.1163 + ((gbPalette[paletteIndex] & 0xff00) | (value))) & 0x7fff; 1.1164 + if (gbMemory[0xff6a] & 0x80) 1.1165 + { 1.1166 + int index = ((gbMemory[0xff6a] & 0x3f) + 1) & 0x3f; 1.1167 + 1.1168 + gbMemory[0xff6a] = (gbMemory[0xff6a] & 0x80) | index; 1.1169 + 1.1170 + gbMemory[0xff6b] = (index & 1 ? 1.1171 + (gbPalette[(index >> 1) + 32] >> 8) : 1.1172 + (gbPalette[(index >> 1) + 32] & 0x00ff)); 1.1173 + } 1.1174 + return; 1.1175 + } 1.1176 + break; 1.1177 + } 1.1178 + 1.1179 + // SVBK 1.1180 + case 0x70: 1.1181 + { 1.1182 + if (gbCgbMode) 1.1183 + { 1.1184 + value = value & 7; 1.1185 + 1.1186 + int bank = value; 1.1187 + if (value == 0) 1.1188 + bank = 1; 1.1189 + 1.1190 + if (bank == gbWramBank) 1.1191 + return; 1.1192 + 1.1193 + int wramAddress = bank * 0x1000; 1.1194 + gbMemoryMap[0x0d] = &gbWram[wramAddress]; 1.1195 + 1.1196 + gbWramBank = bank; 1.1197 + register_SVBK = value; 1.1198 + return; 1.1199 + } 1.1200 + break; 1.1201 + } 1.1202 + 1.1203 + case 0xff: 1.1204 + { 1.1205 + register_IE = value; 1.1206 + register_IF &= value; 1.1207 + return; 1.1208 + } 1.1209 + } 1.1210 + 1.1211 + gbWriteMemoryQuick(address, value); 1.1212 +} 1.1213 + 1.1214 +u8 gbReadOpcode(register u16 address) 1.1215 +{ 1.1216 + if (gbCheatMap[address]) 1.1217 + return gbCheatRead(address); 1.1218 + 1.1219 + // the following fix does more than Echo RAM fix, anyway... 1.1220 + switch (gbEchoRAMFixOn ? (address >> 12) & 0x000f : address & 0xf000) 1.1221 + { 1.1222 + case 0x0a: 1.1223 + case 0x0b: 1.1224 + if (mapperReadRAM) 1.1225 + return mapperReadRAM(address); 1.1226 + break; 1.1227 + case 0x0f: 1.1228 + if (address > 0xff00) 1.1229 + { 1.1230 + switch (address & 0x00ff) 1.1231 + { 1.1232 + case 0x04: 1.1233 + return register_DIV; 1.1234 + case 0x05: 1.1235 + return register_TIMA; 1.1236 + case 0x06: 1.1237 + return register_TMA; 1.1238 + case 0x07: 1.1239 + return (0xf8 | register_TAC); 1.1240 + case 0x0f: 1.1241 + return (0xe0 | register_IF); 1.1242 + case 0x40: 1.1243 + return register_LCDC; 1.1244 + case 0x41: 1.1245 + return (0x80 | register_STAT); 1.1246 + case 0x42: 1.1247 + return register_SCY; 1.1248 + case 0x43: 1.1249 + return register_SCX; 1.1250 + case 0x44: 1.1251 + return register_LY; 1.1252 + case 0x45: 1.1253 + return register_LYC; 1.1254 + case 0x46: 1.1255 + return register_DMA; 1.1256 + case 0x4a: 1.1257 + return register_WY; 1.1258 + case 0x4b: 1.1259 + return register_WX; 1.1260 + case 0x4f: 1.1261 + return (0xfe | register_VBK); 1.1262 + case 0x51: 1.1263 + return register_HDMA1; 1.1264 + case 0x52: 1.1265 + return register_HDMA2; 1.1266 + case 0x53: 1.1267 + return register_HDMA3; 1.1268 + case 0x54: 1.1269 + return register_HDMA4; 1.1270 + case 0x55: 1.1271 + return register_HDMA5; 1.1272 + case 0x70: 1.1273 + return (0xf8 | register_SVBK); 1.1274 + case 0xff: 1.1275 + return register_IE; 1.1276 + } 1.1277 + } 1.1278 + break; 1.1279 + } 1.1280 + return gbReadMemoryQuick(address); 1.1281 +} 1.1282 + 1.1283 +void gbWriteMemory(register u16 address, register u8 value) 1.1284 +{ 1.1285 + gbWriteMemoryWrapped(address, value); 1.1286 + CallRegisteredLuaMemHook(address, 1, value, LUAMEMHOOK_WRITE); 1.1287 +} 1.1288 + 1.1289 +u8 gbReadMemory(register u16 address) 1.1290 +{ 1.1291 + if (gbCheatMap[address]) 1.1292 + return gbCheatRead(address); 1.1293 + 1.1294 + if (address < 0xa000) 1.1295 + return gbReadMemoryQuick(address); 1.1296 + 1.1297 + if (address < 0xc000) 1.1298 + { 1.1299 +#ifndef FINAL_VERSION 1.1300 + if (memorydebug) 1.1301 + { 1.1302 + log("Memory register read %04x PC=%04x\n", 1.1303 + address, 1.1304 + PC.W); 1.1305 + } 1.1306 +#endif 1.1307 + 1.1308 + if (mapperReadRAM) 1.1309 + return mapperReadRAM(address); 1.1310 + return gbReadMemoryQuick(address); 1.1311 + } 1.1312 + 1.1313 + if (address >= 0xff00) 1.1314 + { 1.1315 + switch (address & 0x00ff) 1.1316 + { 1.1317 + case 0x00: 1.1318 + { 1.1319 + if (gbSgbMode) 1.1320 + { 1.1321 + gbSgbReadingController |= 4; 1.1322 + gbSgbResetPacketState(); 1.1323 + } 1.1324 + 1.1325 + int b = gbMemory[0xff00]; 1.1326 + 1.1327 + if ((b & 0x30) == 0x20) 1.1328 + { 1.1329 + b &= 0xf0; 1.1330 + 1.1331 + int joy = 0; 1.1332 + if (gbSgbMode && gbSgbMultiplayer) 1.1333 + { 1.1334 + switch (gbSgbNextController) 1.1335 + { 1.1336 + case 0x0f: 1.1337 + joy = 0; 1.1338 + break; 1.1339 + case 0x0e: 1.1340 + joy = 1; 1.1341 + break; 1.1342 + case 0x0d: 1.1343 + joy = 2; 1.1344 + break; 1.1345 + case 0x0c: 1.1346 + joy = 3; 1.1347 + break; 1.1348 + default: 1.1349 + joy = 0; 1.1350 + } 1.1351 + } 1.1352 + int joystate = gbJoymask[joy]; 1.1353 + if (!(joystate & 128)) 1.1354 + b |= 0x08; 1.1355 + if (!(joystate & 64)) 1.1356 + b |= 0x04; 1.1357 + if (!(joystate & 32)) 1.1358 + b |= 0x02; 1.1359 + if (!(joystate & 16)) 1.1360 + b |= 0x01; 1.1361 + 1.1362 + gbMemory[0xff00] = b; 1.1363 + } 1.1364 + else if ((b & 0x30) == 0x10) 1.1365 + { 1.1366 + b &= 0xf0; 1.1367 + 1.1368 + int joy = 0; 1.1369 + if (gbSgbMode && gbSgbMultiplayer) 1.1370 + { 1.1371 + switch (gbSgbNextController) 1.1372 + { 1.1373 + case 0x0f: 1.1374 + joy = 0; 1.1375 + break; 1.1376 + case 0x0e: 1.1377 + joy = 1; 1.1378 + break; 1.1379 + case 0x0d: 1.1380 + joy = 2; 1.1381 + break; 1.1382 + case 0x0c: 1.1383 + joy = 3; 1.1384 + break; 1.1385 + default: 1.1386 + joy = 0; 1.1387 + } 1.1388 + } 1.1389 + int joystate = gbJoymask[joy]; 1.1390 + if (!(joystate & 8)) 1.1391 + b |= 0x08; 1.1392 + if (!(joystate & 4)) 1.1393 + b |= 0x04; 1.1394 + if (!(joystate & 2)) 1.1395 + b |= 0x02; 1.1396 + if (!(joystate & 1)) 1.1397 + b |= 0x01; 1.1398 + 1.1399 + gbMemory[0xff00] = b; 1.1400 + } 1.1401 + else 1.1402 + { 1.1403 + if (gbSgbMode && gbSgbMultiplayer) 1.1404 + { 1.1405 + gbMemory[0xff00] = 0xf0 | gbSgbNextController; 1.1406 + } 1.1407 + else 1.1408 + { 1.1409 + gbMemory[0xff00] = 0xff; 1.1410 + } 1.1411 + } 1.1412 + } 1.1413 + GBSystemCounters.lagged = false; 1.1414 + return gbMemory[0xff00]; 1.1415 + break; 1.1416 + case 0x01: 1.1417 + return gbMemory[0xff01]; 1.1418 + case 0x04: 1.1419 + return register_DIV; 1.1420 + case 0x05: 1.1421 + return register_TIMA; 1.1422 + case 0x06: 1.1423 + return register_TMA; 1.1424 + case 0x07: 1.1425 + return (0xf8 | register_TAC); 1.1426 + case 0x0f: 1.1427 + return (0xe0 | register_IF); 1.1428 + case 0x40: 1.1429 + return register_LCDC; 1.1430 + case 0x41: 1.1431 + return (0x80 | register_STAT); 1.1432 + case 0x42: 1.1433 + return register_SCY; 1.1434 + case 0x43: 1.1435 + return register_SCX; 1.1436 + case 0x44: 1.1437 + return register_LY; 1.1438 + case 0x45: 1.1439 + return register_LYC; 1.1440 + case 0x46: 1.1441 + return register_DMA; 1.1442 + case 0x4a: 1.1443 + return register_WY; 1.1444 + case 0x4b: 1.1445 + return register_WX; 1.1446 + case 0x4f: 1.1447 + return (0xfe | register_VBK); 1.1448 + case 0x51: 1.1449 + return register_HDMA1; 1.1450 + case 0x52: 1.1451 + return register_HDMA2; 1.1452 + case 0x53: 1.1453 + return register_HDMA3; 1.1454 + case 0x54: 1.1455 + return register_HDMA4; 1.1456 + case 0x55: 1.1457 + return register_HDMA5; 1.1458 + case 0x70: 1.1459 + return (0xf8 | register_SVBK); 1.1460 + case 0xff: 1.1461 + return register_IE; 1.1462 + } 1.1463 + } 1.1464 + 1.1465 + return gbReadMemoryQuick(address); 1.1466 +} 1.1467 + 1.1468 +void gbVblank_interrupt() 1.1469 +{ 1.1470 + if (IFF & 0x80) 1.1471 + { 1.1472 + PC.W++; 1.1473 + IFF &= 0x7f; 1.1474 + } 1.1475 + gbInterrupt &= 0xfe; 1.1476 + 1.1477 + IFF &= 0x7e; 1.1478 + register_IF &= 0xfe; 1.1479 + 1.1480 + gbWriteMemory(--SP.W, PC.B.B1); 1.1481 + gbWriteMemory(--SP.W, PC.B.B0); 1.1482 + PC.W = 0x40; 1.1483 +} 1.1484 + 1.1485 +void gbLcd_interrupt() 1.1486 +{ 1.1487 + if (IFF & 0x80) 1.1488 + { 1.1489 + PC.W++; 1.1490 + IFF &= 0x7f; 1.1491 + } 1.1492 + gbInterrupt &= 0xfd; 1.1493 + IFF &= 0x7e; 1.1494 + register_IF &= 0xfd; 1.1495 + 1.1496 + gbWriteMemory(--SP.W, PC.B.B1); 1.1497 + gbWriteMemory(--SP.W, PC.B.B0); 1.1498 + 1.1499 + PC.W = 0x48; 1.1500 +} 1.1501 + 1.1502 +void gbTimer_interrupt() 1.1503 +{ 1.1504 + if (IFF & 0x80) 1.1505 + { 1.1506 + PC.W++; 1.1507 + IFF &= 0x7f; 1.1508 + } 1.1509 + IFF &= 0x7e; 1.1510 + gbInterrupt &= 0xfb; 1.1511 + register_IF &= 0xfb; 1.1512 + 1.1513 + gbWriteMemory(--SP.W, PC.B.B1); 1.1514 + gbWriteMemory(--SP.W, PC.B.B0); 1.1515 + 1.1516 + PC.W = 0x50; 1.1517 +} 1.1518 + 1.1519 +void gbSerial_interrupt() 1.1520 +{ 1.1521 + if (IFF & 0x80) 1.1522 + { 1.1523 + PC.W++; 1.1524 + IFF &= 0x7f; 1.1525 + } 1.1526 + IFF &= 0x7e; 1.1527 + gbInterrupt &= 0xf7; 1.1528 + register_IF &= 0xf7; 1.1529 + 1.1530 + gbWriteMemory(--SP.W, PC.B.B1); 1.1531 + gbWriteMemory(--SP.W, PC.B.B0); 1.1532 + 1.1533 + PC.W = 0x58; 1.1534 +} 1.1535 + 1.1536 +void gbJoypad_interrupt() 1.1537 +{ 1.1538 + if (IFF & 0x80) 1.1539 + { 1.1540 + PC.W++; 1.1541 + IFF &= 0x7f; 1.1542 + } 1.1543 + IFF &= 0x7e; 1.1544 + gbInterrupt &= 0xef; 1.1545 + register_IF &= 0xef; 1.1546 + 1.1547 + gbWriteMemory(--SP.W, PC.B.B1); 1.1548 + gbWriteMemory(--SP.W, PC.B.B0); 1.1549 + 1.1550 + PC.W = 0x60; 1.1551 +} 1.1552 + 1.1553 +void gbSpeedSwitch() 1.1554 +{ 1.1555 + if (gbSpeed == 0) 1.1556 + { 1.1557 + gbSpeed = 1; 1.1558 + GBLCD_MODE_0_CLOCK_TICKS = 51 * 2; //127; //51 * 2; 1.1559 + GBLCD_MODE_1_CLOCK_TICKS = 1140 * 2; 1.1560 + GBLCD_MODE_2_CLOCK_TICKS = 20 * 2; //52; //20 * 2; 1.1561 + GBLCD_MODE_3_CLOCK_TICKS = 43 * 2; //99; //43 * 2; 1.1562 + GBDIV_CLOCK_TICKS = 64 * 2; 1.1563 + GBLY_INCREMENT_CLOCK_TICKS = 114 * 2; 1.1564 + GBTIMER_MODE_0_CLOCK_TICKS = 256; //256*2; 1.1565 + GBTIMER_MODE_1_CLOCK_TICKS = 4; //4*2; 1.1566 + GBTIMER_MODE_2_CLOCK_TICKS = 16; //16*2; 1.1567 + GBTIMER_MODE_3_CLOCK_TICKS = 64; //64*2; 1.1568 + GBSERIAL_CLOCK_TICKS = 128 * 2; 1.1569 + gbDivTicks *= 2; 1.1570 + gbLcdTicks *= 2; 1.1571 + gbLcdLYIncrementTicks *= 2; 1.1572 + // timerTicks *= 2; 1.1573 + // timerClockTicks *= 2; 1.1574 + gbSerialTicks *= 2; 1.1575 + SOUND_CLOCK_TICKS = soundQuality * GB_USE_TICKS_AS * 2; 1.1576 + soundTicks *= 2; 1.1577 + // synchronizeTicks *= 2; 1.1578 + // SYNCHRONIZE_CLOCK_TICKS *= 2; 1.1579 + } 1.1580 + else 1.1581 + { 1.1582 + gbSpeed = 0; 1.1583 + GBLCD_MODE_0_CLOCK_TICKS = 51; 1.1584 + GBLCD_MODE_1_CLOCK_TICKS = 1140; 1.1585 + GBLCD_MODE_2_CLOCK_TICKS = 20; 1.1586 + GBLCD_MODE_3_CLOCK_TICKS = 43; 1.1587 + GBDIV_CLOCK_TICKS = 64; 1.1588 + GBLY_INCREMENT_CLOCK_TICKS = 114; 1.1589 + GBTIMER_MODE_0_CLOCK_TICKS = 256; 1.1590 + GBTIMER_MODE_1_CLOCK_TICKS = 4; 1.1591 + GBTIMER_MODE_2_CLOCK_TICKS = 16; 1.1592 + GBTIMER_MODE_3_CLOCK_TICKS = 64; 1.1593 + GBSERIAL_CLOCK_TICKS = 128; 1.1594 + gbDivTicks /= 2; 1.1595 + gbLcdTicks /= 2; 1.1596 + gbLcdLYIncrementTicks /= 2; 1.1597 + // timerTicks /= 2; 1.1598 + // timerClockTicks /= 2; 1.1599 + gbSerialTicks /= 2; 1.1600 + SOUND_CLOCK_TICKS = soundQuality * GB_USE_TICKS_AS; 1.1601 + soundTicks /= 2; 1.1602 + // synchronizeTicks /= 2; 1.1603 + // SYNCHRONIZE_CLOCK_TICKS /= 2; 1.1604 + } 1.1605 +} 1.1606 + 1.1607 +void gbGetHardwareType() 1.1608 +{ 1.1609 + gbCgbMode = 0; 1.1610 + if (gbRom[0x143] & 0x80) 1.1611 + { 1.1612 + if (gbEmulatorType == 0 || 1.1613 + gbEmulatorType == 1 || 1.1614 + gbEmulatorType == 4 || 1.1615 + gbEmulatorType == 5 || 1.1616 + (gbRom[0x146] != 0x03 && (gbEmulatorType == 2))) 1.1617 + { 1.1618 + gbCgbMode = 1; 1.1619 + } 1.1620 + } 1.1621 + 1.1622 + if (gbSgbMode == 2) 1.1623 + { 1.1624 + gbSgbMode = 0; 1.1625 + return; 1.1626 + } 1.1627 + 1.1628 + gbSgbMode = 0; 1.1629 + if (gbRom[0x146] == 0x03) 1.1630 + { 1.1631 + if (gbEmulatorType == 0 || 1.1632 + gbEmulatorType == 2 || 1.1633 + gbEmulatorType == 5 || 1.1634 + (!(gbRom[0x143] & 0x80) && (gbEmulatorType == 1 || gbEmulatorType == 4))) 1.1635 + gbSgbMode = 1; 1.1636 + } 1.1637 +} 1.1638 + 1.1639 +void gbReset(bool userReset) 1.1640 +{ 1.1641 + // movie must be closed while opening/creating a movie 1.1642 + if (userReset && VBAMovieRecording()) 1.1643 + { 1.1644 + VBAMovieSignalReset(); 1.1645 + return; 1.1646 + } 1.1647 + 1.1648 + if (!VBAMovieActive()) 1.1649 + { 1.1650 + GBSystemCounters.frameCount = 0; 1.1651 + GBSystemCounters.lagCount = 0; 1.1652 + GBSystemCounters.extraCount = 0; 1.1653 + GBSystemCounters.lagged = true; 1.1654 + GBSystemCounters.laggedLast = true; 1.1655 + } 1.1656 + 1.1657 + SP.W = 0xfffe; 1.1658 + AF.W = 0x01b0; 1.1659 + BC.W = 0x0013; 1.1660 + DE.W = 0x00d8; 1.1661 + HL.W = 0x014d; 1.1662 + PC.W = 0x0100; 1.1663 + IFF = 0; 1.1664 + gbInterrupt = 1; 1.1665 + gbInterruptWait = 0; 1.1666 + 1.1667 + register_DIV = 0; 1.1668 + register_TIMA = 0; 1.1669 + register_TMA = 0; 1.1670 + register_TAC = 0; 1.1671 + register_IF = 1; 1.1672 + register_LCDC = 0x91; 1.1673 + register_STAT = 0; 1.1674 + register_SCY = 0; 1.1675 + register_SCX = 0; 1.1676 + register_LY = 0; 1.1677 + register_LYC = 0; 1.1678 + register_DMA = 0; 1.1679 + register_WY = 0; 1.1680 + register_WX = 0; 1.1681 + register_VBK = 0; 1.1682 + register_HDMA1 = 0; 1.1683 + register_HDMA2 = 0; 1.1684 + register_HDMA3 = 0; 1.1685 + register_HDMA4 = 0; 1.1686 + register_HDMA5 = 0; 1.1687 + register_SVBK = 0; 1.1688 + register_IE = 0; 1.1689 + 1.1690 + gbGetHardwareType(); 1.1691 + if (gbCgbMode) 1.1692 + { 1.1693 + if (!gbVram) 1.1694 + gbVram = (u8 *)malloc(0x4000 + 4); 1.1695 + if (!gbWram) 1.1696 + gbWram = (u8 *)malloc(0x8000 + 4); 1.1697 + memset(gbVram, 0, 0x4000 + 4); 1.1698 + memset(gbWram, 0, 0x8000 + 4); 1.1699 + } 1.1700 + else 1.1701 + { 1.1702 + if (gbVram) 1.1703 + { 1.1704 + free(gbVram); 1.1705 + gbVram = NULL; 1.1706 + } 1.1707 + if (gbWram) 1.1708 + { 1.1709 + free(gbWram); 1.1710 + gbWram = NULL; 1.1711 + } 1.1712 + } 1.1713 + 1.1714 + // clean LineBuffer 1.1715 + if (gbLineBuffer) 1.1716 + memset(gbLineBuffer, 0, 160 * sizeof(u16)); 1.1717 + // clean Pix 1.1718 + if (pix) 1.1719 + memset(pix, 0, 4 * 257 * 226); 1.1720 + 1.1721 + if (gbCgbMode) 1.1722 + { 1.1723 + if (gbSgbMode) 1.1724 + { 1.1725 + if (gbEmulatorType == 5) 1.1726 + AF.W = 0xffb0; 1.1727 + else 1.1728 + AF.W = 0x01b0; 1.1729 + BC.W = 0x0013; 1.1730 + DE.W = 0x00d8; 1.1731 + HL.W = 0x014d; 1.1732 + } 1.1733 + else 1.1734 + { 1.1735 + AF.W = 0x11b0; 1.1736 + BC.W = 0x0000; 1.1737 + DE.W = 0xff56; 1.1738 + HL.W = 0x000d; 1.1739 + } 1.1740 + if (gbEmulatorType == 4) 1.1741 + BC.B.B1 |= 0x01; 1.1742 + 1.1743 + register_HDMA5 = 0xff; 1.1744 + gbMemory[0xff68] = 0xc0; 1.1745 + gbMemory[0xff6a] = 0xc0; 1.1746 + 1.1747 + for (int i = 0; i < 64; i++) 1.1748 + gbPalette[i] = 0x7fff; 1.1749 + } 1.1750 + else 1.1751 + { 1.1752 + for (int i = 0; i < 8; i++) 1.1753 + gbPalette[i] = systemGbPalette[gbPaletteOption * 8 + i]; 1.1754 + } 1.1755 + 1.1756 + if (gbSpeed) 1.1757 + { 1.1758 + gbSpeedSwitch(); 1.1759 + gbMemory[0xff4d] = 0; 1.1760 + } 1.1761 + 1.1762 + gbDivTicks = GBDIV_CLOCK_TICKS; 1.1763 + gbLcdMode = 2; 1.1764 + gbLcdTicks = GBLCD_MODE_2_CLOCK_TICKS; 1.1765 + gbLcdLYIncrementTicks = 0; 1.1766 + gbTimerTicks = 0; 1.1767 + gbTimerClockTicks = 0; 1.1768 + gbSerialTicks = 0; 1.1769 + gbSerialBits = 0; 1.1770 + gbSerialOn = 0; 1.1771 + gbWindowLine = -1; 1.1772 + gbTimerOn = 0; 1.1773 + gbTimerMode = 0; 1.1774 + // gbSynchronizeTicks = GBSYNCHRONIZE_CLOCK_TICKS; 1.1775 + gbSpeed = 0; 1.1776 + gbJoymask[0] = gbJoymask[1] = gbJoymask[2] = gbJoymask[3] = 0; 1.1777 + 1.1778 + // FIXME: horrible kludge 1.1779 + memset(s_gbJoymask, 0, sizeof(s_gbJoymask)); 1.1780 + 1.1781 + if (gbCgbMode) 1.1782 + { 1.1783 + gbSpeed = 0; 1.1784 + gbHdmaOn = 0; 1.1785 + gbHdmaSource = 0x0000; 1.1786 + gbHdmaDestination = 0x8000; 1.1787 + gbVramBank = 0; 1.1788 + gbWramBank = 1; 1.1789 + register_LY = 0x90; 1.1790 + gbLcdMode = 1; 1.1791 + } 1.1792 + 1.1793 + if (gbSgbMode) 1.1794 + { 1.1795 + gbSgbReset(); 1.1796 + } 1.1797 + 1.1798 + for (int i = 0; i < 4; i++) 1.1799 + gbBgp[i] = gbObp0[i] = gbObp1[i] = i; 1.1800 + 1.1801 + memset(&gbDataMBC1, 0, sizeof(gbDataMBC1)); 1.1802 + gbDataMBC1.mapperROMBank = 1; 1.1803 + 1.1804 + gbDataMBC2.mapperRAMEnable = 0; 1.1805 + gbDataMBC2.mapperROMBank = 1; 1.1806 + 1.1807 + memset(&gbDataMBC3, 0, 6 * sizeof(int32)); 1.1808 + gbDataMBC3.mapperROMBank = 1; 1.1809 + 1.1810 + memset(&gbDataMBC5, 0, sizeof(gbDataMBC5)); 1.1811 + gbDataMBC5.mapperROMBank = 1; 1.1812 + switch (gbRom[0x147]) 1.1813 + { 1.1814 + case 0x1c: 1.1815 + case 0x1d: 1.1816 + case 0x1e: 1.1817 + gbDataMBC5.isRumbleCartridge = 1; 1.1818 + } 1.1819 + 1.1820 + memset(&gbDataHuC1, 0, sizeof(gbDataHuC1)); 1.1821 + gbDataHuC1.mapperROMBank = 1; 1.1822 + 1.1823 + memset(&gbDataHuC3, 0, sizeof(gbDataHuC3)); 1.1824 + gbDataHuC3.mapperROMBank = 1; 1.1825 + 1.1826 + gbMemoryMap[0x00] = &gbRom[0x0000]; 1.1827 + gbMemoryMap[0x01] = &gbRom[0x1000]; 1.1828 + gbMemoryMap[0x02] = &gbRom[0x2000]; 1.1829 + gbMemoryMap[0x03] = &gbRom[0x3000]; 1.1830 + gbMemoryMap[0x04] = &gbRom[0x4000]; 1.1831 + gbMemoryMap[0x05] = &gbRom[0x5000]; 1.1832 + gbMemoryMap[0x06] = &gbRom[0x6000]; 1.1833 + gbMemoryMap[0x07] = &gbRom[0x7000]; 1.1834 + if (gbCgbMode) 1.1835 + { 1.1836 + gbMemoryMap[0x08] = &gbVram[0x0000]; 1.1837 + gbMemoryMap[0x09] = &gbVram[0x1000]; 1.1838 + gbMemoryMap[0x0a] = &gbMemory[0xa000]; 1.1839 + gbMemoryMap[0x0b] = &gbMemory[0xb000]; 1.1840 + gbMemoryMap[0x0c] = &gbMemory[0xc000]; 1.1841 + gbMemoryMap[0x0d] = &gbWram[0x1000]; 1.1842 + gbMemoryMap[0x0e] = &gbMemory[0xe000]; 1.1843 + gbMemoryMap[0x0f] = &gbMemory[0xf000]; 1.1844 + } 1.1845 + else 1.1846 + { 1.1847 + gbMemoryMap[0x08] = &gbMemory[0x8000]; 1.1848 + gbMemoryMap[0x09] = &gbMemory[0x9000]; 1.1849 + gbMemoryMap[0x0a] = &gbMemory[0xa000]; 1.1850 + gbMemoryMap[0x0b] = &gbMemory[0xb000]; 1.1851 + gbMemoryMap[0x0c] = &gbMemory[0xc000]; 1.1852 + gbMemoryMap[0x0d] = &gbMemory[0xd000]; 1.1853 + gbMemoryMap[0x0e] = &gbMemory[0xe000]; 1.1854 + gbMemoryMap[0x0f] = &gbMemory[0xf000]; 1.1855 + } 1.1856 + 1.1857 + if (gbRam) 1.1858 + { 1.1859 + gbMemoryMap[0x0a] = &gbRam[0x0000]; 1.1860 + gbMemoryMap[0x0b] = &gbRam[0x1000]; 1.1861 + } 1.1862 + 1.1863 + gbSoundReset(); 1.1864 + 1.1865 + systemResetSensor(); 1.1866 + 1.1867 + systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED; 1.1868 + 1.1869 + gbLastTime = systemGetClock(); 1.1870 + gbFrameCount = 0; 1.1871 + 1.1872 + systemRefreshScreen(); 1.1873 +} 1.1874 + 1.1875 +void gbWriteSaveMBC1(const char *name) 1.1876 +{ 1.1877 + FILE *gzFile = fopen(name, "wb"); 1.1878 + 1.1879 + if (gzFile == NULL) 1.1880 + { 1.1881 + systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name); 1.1882 + return; 1.1883 + } 1.1884 + 1.1885 + fwrite(gbRam, 1.1886 + 1, 1.1887 + gbRamSize, 1.1888 + gzFile); 1.1889 + 1.1890 + fclose(gzFile); 1.1891 +} 1.1892 + 1.1893 +void gbWriteSaveMBC2(const char *name) 1.1894 +{ 1.1895 + FILE *file = fopen(name, "wb"); 1.1896 + 1.1897 + if (file == NULL) 1.1898 + { 1.1899 + systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name); 1.1900 + return; 1.1901 + } 1.1902 + 1.1903 + fwrite(&gbMemory[0xa000], 1.1904 + 1, 1.1905 + 256, 1.1906 + file); 1.1907 + 1.1908 + fclose(file); 1.1909 +} 1.1910 + 1.1911 +void gbWriteSaveMBC3(const char *name, bool extendedSave) 1.1912 +{ 1.1913 + FILE *gzFile = fopen(name, "wb"); 1.1914 + 1.1915 + if (gzFile == NULL) 1.1916 + { 1.1917 + systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name); 1.1918 + return; 1.1919 + } 1.1920 + 1.1921 + fwrite(gbRam, 1.1922 + 1, 1.1923 + gbRamSize, 1.1924 + gzFile); 1.1925 + 1.1926 + if (extendedSave) 1.1927 + { 1.1928 + //assert(sizeof(time_t) == 4); 1.1929 + fwrite(&gbDataMBC3.mapperSeconds, 1.1930 + 1, 1.1931 + 10 * sizeof(int32) + /*sizeof(time_t)*/4, 1.1932 + gzFile); 1.1933 + } 1.1934 + 1.1935 + fclose(gzFile); 1.1936 +} 1.1937 + 1.1938 +void gbWriteSaveMBC5(const char *name) 1.1939 +{ 1.1940 + FILE *gzFile = fopen(name, "wb"); 1.1941 + 1.1942 + if (gzFile == NULL) 1.1943 + { 1.1944 + systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name); 1.1945 + return; 1.1946 + } 1.1947 + 1.1948 + fwrite(gbRam, 1.1949 + 1, 1.1950 + gbRamSize, 1.1951 + gzFile); 1.1952 + 1.1953 + fclose(gzFile); 1.1954 +} 1.1955 + 1.1956 +void gbWriteSaveMBC7(const char *name) 1.1957 +{ 1.1958 + FILE *file = fopen(name, "wb"); 1.1959 + 1.1960 + if (file == NULL) 1.1961 + { 1.1962 + systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name); 1.1963 + return; 1.1964 + } 1.1965 + 1.1966 + fwrite(&gbMemory[0xa000], 1.1967 + 1, 1.1968 + 256, 1.1969 + file); 1.1970 + 1.1971 + fclose(file); 1.1972 +} 1.1973 + 1.1974 +bool gbReadSaveMBC1(const char *name) 1.1975 +{ 1.1976 + gzFile gzFile = gzopen(name, "rb"); 1.1977 + 1.1978 + if (gzFile == NULL) 1.1979 + { 1.1980 + return false; 1.1981 + } 1.1982 + 1.1983 + int read = gzread(gzFile, 1.1984 + gbRam, 1.1985 + gbRamSize); 1.1986 + 1.1987 + if (read != gbRamSize) 1.1988 + { 1.1989 + systemMessage(MSG_FAILED_TO_READ_SGM, N_("Failed to read complete save game %s (%d)"), name, read); 1.1990 + gzclose(gzFile); 1.1991 + return false; 1.1992 + } 1.1993 + 1.1994 + gzclose(gzFile); 1.1995 + return true; 1.1996 +} 1.1997 + 1.1998 +bool gbReadSaveMBC2(const char *name) 1.1999 +{ 1.2000 + FILE *file = fopen(name, "rb"); 1.2001 + 1.2002 + if (file == NULL) 1.2003 + { 1.2004 + return false; 1.2005 + } 1.2006 + 1.2007 + int read = fread(&gbMemory[0xa000], 1.2008 + 1, 1.2009 + 256, 1.2010 + file); 1.2011 + 1.2012 + if (read != 256) 1.2013 + { 1.2014 + systemMessage(MSG_FAILED_TO_READ_SGM, 1.2015 + N_("Failed to read complete save game %s (%d)"), name, read); 1.2016 + fclose(file); 1.2017 + return false; 1.2018 + } 1.2019 + 1.2020 + fclose(file); 1.2021 + return true; 1.2022 +} 1.2023 + 1.2024 +bool gbReadSaveMBC3(const char *name) 1.2025 +{ 1.2026 + gzFile gzFile = gzopen(name, "rb"); 1.2027 + 1.2028 + if (gzFile == NULL) 1.2029 + { 1.2030 + return false; 1.2031 + } 1.2032 + 1.2033 + int read = gzread(gzFile, 1.2034 + gbRam, 1.2035 + gbRamSize); 1.2036 + 1.2037 + bool res = true; 1.2038 + 1.2039 + if (read != gbRamSize) 1.2040 + { 1.2041 + systemMessage(MSG_FAILED_TO_READ_SGM, 1.2042 + N_("Failed to read complete save game %s (%d)"), name, read); 1.2043 + } 1.2044 + else 1.2045 + { 1.2046 + //assert(sizeof(time_t) == 4); 1.2047 + read = gzread(gzFile, 1.2048 + &gbDataMBC3.mapperSeconds, 1.2049 + sizeof(int32) * 10 + /*sizeof(time_t)*/4); 1.2050 + 1.2051 + if (read != (sizeof(int32) * 10 + /*sizeof(time_t)*/4) && read != 0) 1.2052 + { 1.2053 + systemMessage(MSG_FAILED_TO_READ_RTC, 1.2054 + N_("Failed to read RTC from save game %s (continuing)"), 1.2055 + name); 1.2056 + res = false; 1.2057 + } 1.2058 + } 1.2059 + 1.2060 + gzclose(gzFile); 1.2061 + return res; 1.2062 +} 1.2063 + 1.2064 +bool gbReadSaveMBC5(const char *name) 1.2065 +{ 1.2066 + gzFile gzFile = gzopen(name, "rb"); 1.2067 + 1.2068 + if (gzFile == NULL) 1.2069 + { 1.2070 + return false; 1.2071 + } 1.2072 + 1.2073 + int read = gzread(gzFile, 1.2074 + gbRam, 1.2075 + gbRamSize); 1.2076 + 1.2077 + if (read != gbRamSize) 1.2078 + { 1.2079 + systemMessage(MSG_FAILED_TO_READ_SGM, 1.2080 + N_("Failed to read complete save game %s (%d)"), name, read); 1.2081 + gzclose(gzFile); 1.2082 + return false; 1.2083 + } 1.2084 + 1.2085 + gzclose(gzFile); 1.2086 + return true; 1.2087 +} 1.2088 + 1.2089 +bool gbReadSaveMBC7(const char *name) 1.2090 +{ 1.2091 + FILE *file = fopen(name, "rb"); 1.2092 + 1.2093 + if (file == NULL) 1.2094 + { 1.2095 + return false; 1.2096 + } 1.2097 + 1.2098 + int read = fread(&gbMemory[0xa000], 1.2099 + 1, 1.2100 + 256, 1.2101 + file); 1.2102 + 1.2103 + if (read != 256) 1.2104 + { 1.2105 + systemMessage(MSG_FAILED_TO_READ_SGM, 1.2106 + N_("Failed to read complete save game %s (%d)"), name, read); 1.2107 + fclose(file); 1.2108 + return false; 1.2109 + } 1.2110 + 1.2111 + fclose(file); 1.2112 + return true; 1.2113 +} 1.2114 + 1.2115 +#if 0 1.2116 +bool gbLoadBIOS(const char *biosFileName, bool useBiosFile) 1.2117 +{ 1.2118 + useBios = false; 1.2119 + if (useBiosFile) 1.2120 + { 1.2121 + useBios = utilLoadBIOS(bios, biosFileName, gbEmulatorType); 1.2122 + if (!useBios) 1.2123 + { 1.2124 + systemMessage(MSG_INVALID_BIOS_FILE_SIZE, N_("Invalid BOOTROM file")); 1.2125 + } 1.2126 + } 1.2127 + return useBios; 1.2128 +} 1.2129 +#endif 1.2130 + 1.2131 +void gbInit() 1.2132 +{ 1.2133 + gbGenFilter(); 1.2134 + gbSgbInit(); // calls gbSgbReset()... whatever 1.2135 + 1.2136 + gbMemory = (u8 *)malloc(65536 + 4); 1.2137 + memset(gbMemory, 0, 65536 + 4); 1.2138 + memset(gbPalette, 0, 2 * 128); 1.2139 + 1.2140 + // HACK: +4 at start to accomodate the 2xSaI filter reading out of bounds of the leftmost pixel 1.2141 + origPix = (u8 *)calloc(1, 4 * 257 * 226 + 4); 1.2142 + pix = origPix + 4; 1.2143 + 1.2144 + gbLineBuffer = (u16 *)malloc(160 * sizeof(u16)); 1.2145 +} 1.2146 + 1.2147 +bool gbWriteBatteryFile(const char *file, bool extendedSave) 1.2148 +{ 1.2149 + if (gbBattery) 1.2150 + { 1.2151 + int type = gbRom[0x147]; 1.2152 + 1.2153 + switch (type) 1.2154 + { 1.2155 + case 0x03: 1.2156 + gbWriteSaveMBC1(file); 1.2157 + break; 1.2158 + case 0x06: 1.2159 + gbWriteSaveMBC2(file); 1.2160 + break; 1.2161 + case 0x0f: 1.2162 + case 0x10: 1.2163 + case 0x13: 1.2164 + gbWriteSaveMBC3(file, extendedSave); 1.2165 + break; 1.2166 + case 0x1b: 1.2167 + case 0x1e: 1.2168 + gbWriteSaveMBC5(file); 1.2169 + break; 1.2170 + case 0x22: 1.2171 + gbWriteSaveMBC7(file); 1.2172 + break; 1.2173 + case 0xff: 1.2174 + gbWriteSaveMBC1(file); 1.2175 + break; 1.2176 + } 1.2177 + } 1.2178 + return true; 1.2179 +} 1.2180 + 1.2181 +bool gbWriteBatteryFile(const char *file) 1.2182 +{ 1.2183 + gbWriteBatteryFile(file, true); 1.2184 + return true; 1.2185 +} 1.2186 + 1.2187 +bool gbWriteBatteryToStream(gzFile gzfile) 1.2188 +{ 1.2189 + // the GB save code is ugly, so rather than convert it all to use gzFiles, just save it to a temp file... 1.2190 +#define TEMP_SAVE_FNAME ("tempvbawrite.sav") 1.2191 + bool retVal = gbWriteBatteryFile(TEMP_SAVE_FNAME, true); 1.2192 + 1.2193 + // ...open the temp file and figure out its size... 1.2194 + FILE *fileTemp = fopen(TEMP_SAVE_FNAME, "rb"); 1.2195 + if (fileTemp == NULL) 1.2196 + return false; 1.2197 + fseek(fileTemp, 0, SEEK_END); 1.2198 + int len = (int) ftell(fileTemp); 1.2199 + 1.2200 + // ...copy over the temp file... 1.2201 + char *temp = new char [len]; 1.2202 + fseek(fileTemp, 0, SEEK_SET); 1.2203 + if (fread(temp, len, 1, fileTemp) != 1) 1.2204 + { 1.2205 + delete [] temp; 1.2206 + fclose(fileTemp); 1.2207 + return false; 1.2208 + } 1.2209 + fclose(fileTemp); 1.2210 + utilGzWrite(gzfile, temp, len); 1.2211 + delete [] temp; 1.2212 + 1.2213 + // ... and delete the temp file 1.2214 + remove(TEMP_SAVE_FNAME); 1.2215 +#undef TEMP_SAVE_FNAME 1.2216 + 1.2217 + return retVal; 1.2218 +} 1.2219 + 1.2220 +bool gbReadBatteryFile(const char *file) 1.2221 +{ 1.2222 + bool res = false; 1.2223 + if (gbBattery) 1.2224 + { 1.2225 + int type = gbRom[0x147]; 1.2226 + 1.2227 + switch (type) 1.2228 + { 1.2229 + case 0x03: 1.2230 + res = gbReadSaveMBC1(file); 1.2231 + break; 1.2232 + case 0x06: 1.2233 + res = gbReadSaveMBC2(file); 1.2234 + break; 1.2235 + case 0x0f: 1.2236 + case 0x10: 1.2237 + case 0x13: 1.2238 + if (!gbReadSaveMBC3(file)) 1.2239 + { 1.2240 + struct tm *lt; 1.2241 + time_t tmp; //Small kludge to get it working on some systems where time_t has size 8. 1.2242 + 1.2243 + if (VBAMovieActive() || VBAMovieLoading()) 1.2244 + { 1.2245 + gbDataMBC3.mapperLastTime = VBAMovieGetId() + VBAMovieGetFrameCounter() / 60; 1.2246 + lt = gmtime(&tmp); 1.2247 + gbDataMBC3.mapperLastTime=(u32)tmp; 1.2248 + } 1.2249 + else 1.2250 + { 1.2251 + time(&tmp); 1.2252 + gbDataMBC3.mapperLastTime=(u32)tmp; 1.2253 + lt = localtime(&tmp); 1.2254 + } 1.2255 + systemScreenMessage(ctime(&tmp), 4); 1.2256 + gbDataMBC3.mapperLastTime=(u32)tmp; 1.2257 + 1.2258 + gbDataMBC3.mapperSeconds = lt->tm_sec; 1.2259 + gbDataMBC3.mapperMinutes = lt->tm_min; 1.2260 + gbDataMBC3.mapperHours = lt->tm_hour; 1.2261 + gbDataMBC3.mapperDays = lt->tm_yday & 255; 1.2262 + gbDataMBC3.mapperControl = (gbDataMBC3.mapperControl & 0xfe) | 1.2263 + (lt->tm_yday > 255 ? 1 : 0); 1.2264 + res = false; 1.2265 + break; 1.2266 + } 1.2267 + time_t tmp; 1.2268 + systemScreenMessage(ctime(&tmp), 4); 1.2269 + gbDataMBC3.mapperLastTime=(u32)tmp; 1.2270 + res = true; 1.2271 + break; 1.2272 + case 0x1b: 1.2273 + case 0x1e: 1.2274 + res = gbReadSaveMBC5(file); 1.2275 + break; 1.2276 + case 0x22: 1.2277 + res = gbReadSaveMBC7(file); 1.2278 + case 0xff: 1.2279 + res = gbReadSaveMBC1(file); 1.2280 + break; 1.2281 + } 1.2282 + } 1.2283 + systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED; 1.2284 + return res; 1.2285 +} 1.2286 + 1.2287 +bool gbReadBatteryFromStream(gzFile gzfile) 1.2288 +{ 1.2289 + // the GB save code is ugly, so rather than convert it all to use gzFiles, just copy it to temp RAM... 1.2290 +#define TEMP_SAVE_FNAME ("tempvbaread.sav") 1.2291 + int pos = gztell(gzfile); 1.2292 + int buflen = 1024; 1.2293 + // ...make a temp file and write it there... 1.2294 + FILE *fileTemp = fopen(TEMP_SAVE_FNAME, "wb"); 1.2295 + if (fileTemp == NULL) 1.2296 + return false; 1.2297 + int gzDeflated; 1.2298 + char *temp = new char [buflen]; 1.2299 + while ((gzDeflated = utilGzRead(gzfile, temp, buflen)) != 0) 1.2300 + { 1.2301 + if (gzDeflated == -1 || fwrite(temp, gzDeflated, 1, fileTemp) != 1) 1.2302 + { 1.2303 + delete [] temp; 1.2304 + fclose(fileTemp); 1.2305 + gzseek(gzfile, pos, SEEK_SET); /// FIXME: leaves pos in gzfile before save instead of after it (everything that 1.2306 + // calls this right now does a seek afterwards so it doesn't matter for now, but it's 1.2307 + // still bad) 1.2308 + return false; 1.2309 + } 1.2310 + } 1.2311 + gzseek(gzfile, pos, SEEK_SET); /// FIXME: leaves pos in gzfile before save instead of after it (everything that calls this 1.2312 + // right now does a seek afterwards so it doesn't matter for now, but it's still bad) 1.2313 + fclose(fileTemp); 1.2314 + delete [] temp; 1.2315 + 1.2316 + // ... load from the temp file... 1.2317 + bool retVal = gbReadBatteryFile(TEMP_SAVE_FNAME); 1.2318 + 1.2319 + // ... and delete the temp file 1.2320 + remove(TEMP_SAVE_FNAME); 1.2321 +#undef TEMP_SAVE_FNAME 1.2322 + 1.2323 + return retVal; 1.2324 +} 1.2325 + 1.2326 +bool gbReadGSASnapshot(const char *fileName) 1.2327 +{ 1.2328 + FILE *file = fopen(fileName, "rb"); 1.2329 + 1.2330 + if (!file) 1.2331 + { 1.2332 + systemMessage(MSG_CANNOT_OPEN_FILE, N_("Cannot open file %s"), fileName); 1.2333 + return false; 1.2334 + } 1.2335 + 1.2336 + // long size = ftell(file); 1.2337 + fseek(file, 0x4, SEEK_SET); 1.2338 + char buffer[16]; 1.2339 + char buffer2[16]; 1.2340 + fread(buffer, 1, 15, file); 1.2341 + buffer[15] = 0; 1.2342 + memcpy(buffer2, &gbRom[0x134], 15); 1.2343 + buffer2[15] = 0; 1.2344 + if (memcmp(buffer, buffer2, 15)) 1.2345 + { 1.2346 + systemMessage(MSG_CANNOT_IMPORT_SNAPSHOT_FOR, 1.2347 + N_("Cannot import snapshot for %s. Current game is %s"), 1.2348 + buffer, 1.2349 + buffer2); 1.2350 + fclose(file); 1.2351 + return false; 1.2352 + } 1.2353 + fseek(file, 0x13, SEEK_SET); 1.2354 + int read = 0; 1.2355 + int toRead = 0; 1.2356 + switch (gbRom[0x147]) 1.2357 + { 1.2358 + case 0x03: 1.2359 + case 0x0f: 1.2360 + case 0x10: 1.2361 + case 0x13: 1.2362 + case 0x1b: 1.2363 + case 0x1e: 1.2364 + case 0xff: 1.2365 + read = fread(gbRam, 1, gbRamSize, file); 1.2366 + toRead = gbRamSize; 1.2367 + break; 1.2368 + case 0x06: 1.2369 + case 0x22: 1.2370 + read = fread(&gbMemory[0xa000], 1, 256, file); 1.2371 + toRead = 256; 1.2372 + break; 1.2373 + default: 1.2374 + systemMessage(MSG_UNSUPPORTED_SNAPSHOT_FILE, 1.2375 + N_("Unsupported snapshot file %s"), 1.2376 + fileName); 1.2377 + fclose(file); 1.2378 + return false; 1.2379 + } 1.2380 + fclose(file); 1.2381 + gbReset(); 1.2382 + return true; 1.2383 +} 1.2384 + 1.2385 +variable_desc gbSaveGameStruct[] = 1.2386 +{ 1.2387 + { &PC.W, sizeof(u16) }, 1.2388 + { &SP.W, sizeof(u16) }, 1.2389 + { &AF.W, sizeof(u16) }, 1.2390 + { &BC.W, sizeof(u16) }, 1.2391 + { &DE.W, sizeof(u16) }, 1.2392 + { &HL.W, sizeof(u16) }, 1.2393 + { &IFF, sizeof(u8) }, 1.2394 + { &GBLCD_MODE_0_CLOCK_TICKS, sizeof(int32) }, 1.2395 + { &GBLCD_MODE_1_CLOCK_TICKS, sizeof(int32) }, 1.2396 + { &GBLCD_MODE_2_CLOCK_TICKS, sizeof(int32) }, 1.2397 + { &GBLCD_MODE_3_CLOCK_TICKS, sizeof(int32) }, 1.2398 + { &GBDIV_CLOCK_TICKS, sizeof(int32) }, 1.2399 + { &GBLY_INCREMENT_CLOCK_TICKS, sizeof(int32) }, 1.2400 + { &GBTIMER_MODE_0_CLOCK_TICKS, sizeof(int32) }, 1.2401 + { &GBTIMER_MODE_1_CLOCK_TICKS, sizeof(int32) }, 1.2402 + { &GBTIMER_MODE_2_CLOCK_TICKS, sizeof(int32) }, 1.2403 + { &GBTIMER_MODE_3_CLOCK_TICKS, sizeof(int32) }, 1.2404 + { &GBSERIAL_CLOCK_TICKS, sizeof(int32) }, 1.2405 + { &GBSYNCHRONIZE_CLOCK_TICKS, sizeof(int32) }, 1.2406 + { &gbDivTicks, sizeof(int32) }, 1.2407 + { &gbLcdMode, sizeof(int32) }, 1.2408 + { &gbLcdTicks, sizeof(int32) }, 1.2409 + { &gbLcdLYIncrementTicks, sizeof(int32) }, 1.2410 + { &gbTimerTicks, sizeof(int32) }, 1.2411 + { &gbTimerClockTicks, sizeof(int32) }, 1.2412 + { &gbSerialTicks, sizeof(int32) }, 1.2413 + { &gbSerialBits, sizeof(int32) }, 1.2414 + { &gbInterrupt, sizeof(int32) }, 1.2415 + { &gbInterruptWait, sizeof(int32) }, 1.2416 + { &gbSynchronizeTicks, sizeof(int32) }, 1.2417 + { &gbTimerOn, sizeof(int32) }, 1.2418 + { &gbTimerMode, sizeof(int32) }, 1.2419 + { &gbSerialOn, sizeof(int32) }, 1.2420 + { &gbWindowLine, sizeof(int32) }, 1.2421 + { &gbCgbMode, sizeof(int32) }, 1.2422 + { &gbVramBank, sizeof(int32) }, 1.2423 + { &gbWramBank, sizeof(int32) }, 1.2424 + { &gbHdmaSource, sizeof(int32) }, 1.2425 + { &gbHdmaDestination, sizeof(int32) }, 1.2426 + { &gbHdmaBytes, sizeof(int32) }, 1.2427 + { &gbHdmaOn, sizeof(int32) }, 1.2428 + { &gbSpeed, sizeof(int32) }, 1.2429 + { &gbSgbMode, sizeof(int32) }, 1.2430 + { ®ister_DIV, sizeof(u8) }, 1.2431 + { ®ister_TIMA, sizeof(u8) }, 1.2432 + { ®ister_TMA, sizeof(u8) }, 1.2433 + { ®ister_TAC, sizeof(u8) }, 1.2434 + { ®ister_IF, sizeof(u8) }, 1.2435 + { ®ister_LCDC, sizeof(u8) }, 1.2436 + { ®ister_STAT, sizeof(u8) }, 1.2437 + { ®ister_SCY, sizeof(u8) }, 1.2438 + { ®ister_SCX, sizeof(u8) }, 1.2439 + { ®ister_LY, sizeof(u8) }, 1.2440 + { ®ister_LYC, sizeof(u8) }, 1.2441 + { ®ister_DMA, sizeof(u8) }, 1.2442 + { ®ister_WY, sizeof(u8) }, 1.2443 + { ®ister_WX, sizeof(u8) }, 1.2444 + { ®ister_VBK, sizeof(u8) }, 1.2445 + { ®ister_HDMA1, sizeof(u8) }, 1.2446 + { ®ister_HDMA2, sizeof(u8) }, 1.2447 + { ®ister_HDMA3, sizeof(u8) }, 1.2448 + { ®ister_HDMA4, sizeof(u8) }, 1.2449 + { ®ister_HDMA5, sizeof(u8) }, 1.2450 + { ®ister_SVBK, sizeof(u8) }, 1.2451 + { ®ister_IE, sizeof(u8) }, 1.2452 + { &gbBgp[0], sizeof(u8) }, 1.2453 + { &gbBgp[1], sizeof(u8) }, 1.2454 + { &gbBgp[2], sizeof(u8) }, 1.2455 + { &gbBgp[3], sizeof(u8) }, 1.2456 + { &gbObp0[0], sizeof(u8) }, 1.2457 + { &gbObp0[1], sizeof(u8) }, 1.2458 + { &gbObp0[2], sizeof(u8) }, 1.2459 + { &gbObp0[3], sizeof(u8) }, 1.2460 + { &gbObp1[0], sizeof(u8) }, 1.2461 + { &gbObp1[1], sizeof(u8) }, 1.2462 + { &gbObp1[2], sizeof(u8) }, 1.2463 + { &gbObp1[3], sizeof(u8) }, 1.2464 + { NULL, 0 } 1.2465 +}; 1.2466 + 1.2467 +bool gbWriteSaveStateToStream(gzFile gzFile) 1.2468 +{ 1.2469 + utilWriteInt(gzFile, GBSAVE_GAME_VERSION); 1.2470 + 1.2471 + utilGzWrite(gzFile, &gbRom[0x134], 15); 1.2472 + 1.2473 + utilWriteData(gzFile, gbSaveGameStruct); 1.2474 + 1.2475 + utilGzWrite(gzFile, &IFF, 2); 1.2476 + 1.2477 + if (gbSgbMode) 1.2478 + { 1.2479 + gbSgbSaveGame(gzFile); 1.2480 + } 1.2481 + 1.2482 + utilGzWrite(gzFile, &gbDataMBC1, sizeof(gbDataMBC1)); 1.2483 + utilGzWrite(gzFile, &gbDataMBC2, sizeof(gbDataMBC2)); 1.2484 + //assert(sizeof(time_t) == 4); 1.2485 + utilGzWrite(gzFile, &gbDataMBC3, sizeof(gbDataMBC3)); 1.2486 + utilGzWrite(gzFile, &gbDataMBC5, sizeof(gbDataMBC5)); 1.2487 + utilGzWrite(gzFile, &gbDataHuC1, sizeof(gbDataHuC1)); 1.2488 + utilGzWrite(gzFile, &gbDataHuC3, sizeof(gbDataHuC3)); 1.2489 + 1.2490 + // yes, this definitely needs to be saved, or loading paused games will show a black screen 1.2491 + // this is also necessary to be consistent with what the GBA saving does 1.2492 + utilGzWrite(gzFile, pix, 4 * 257 * 226); 1.2493 + 1.2494 + utilGzWrite(gzFile, gbPalette, 128 * sizeof(u16)); 1.2495 + // todo: remove 1.2496 + utilGzWrite(gzFile, gbPalette, 128 * sizeof(u16)); 1.2497 + 1.2498 + utilGzWrite(gzFile, &gbMemory[0x8000], 0x8000); 1.2499 + 1.2500 + if (gbRamSize && gbRam) 1.2501 + { 1.2502 + utilGzWrite(gzFile, gbRam, gbRamSize); 1.2503 + } 1.2504 + 1.2505 + if (gbCgbMode) 1.2506 + { 1.2507 + utilGzWrite(gzFile, gbVram, 0x4000); 1.2508 + utilGzWrite(gzFile, gbWram, 0x8000); 1.2509 + } 1.2510 + 1.2511 + gbSoundSaveGame(gzFile); 1.2512 + 1.2513 + gbCheatsSaveGame(gzFile); 1.2514 + 1.2515 + // new to re-recording version: 1.2516 + { 1.2517 + extern int32 sensorX, sensorY; 1.2518 + utilGzWrite(gzFile, &sensorX, sizeof(sensorX)); 1.2519 + utilGzWrite(gzFile, &sensorY, sizeof(sensorY)); 1.2520 + utilGzWrite(gzFile, gbJoymask, 4 * sizeof(*gbJoymask)); // this has to be saved or old input will incorrectly get 1.2521 + // carried 1.2522 + // back on loading a snapshot! 1.2523 + 1.2524 + bool8 movieActive = VBAMovieActive(); 1.2525 + utilGzWrite(gzFile, &movieActive, sizeof(movieActive)); 1.2526 + if (movieActive) 1.2527 + { 1.2528 + uint8 *movie_freeze_buf = NULL; 1.2529 + uint32 movie_freeze_size = 0; 1.2530 + 1.2531 + VBAMovieFreeze(&movie_freeze_buf, &movie_freeze_size); 1.2532 + if (movie_freeze_buf) 1.2533 + { 1.2534 + utilGzWrite(gzFile, &movie_freeze_size, sizeof(movie_freeze_size)); 1.2535 + utilGzWrite(gzFile, movie_freeze_buf, movie_freeze_size); 1.2536 + delete [] movie_freeze_buf; 1.2537 + } 1.2538 + else 1.2539 + { 1.2540 + systemMessage(0, N_("Failed to save movie snapshot.")); 1.2541 + return false; 1.2542 + } 1.2543 + } 1.2544 + utilGzWrite(gzFile, &GBSystemCounters.frameCount, sizeof(GBSystemCounters.frameCount)); 1.2545 + } 1.2546 + 1.2547 + // new to rerecording 19.4 wip (svn r22+): 1.2548 + { 1.2549 + utilGzWrite(gzFile, &GBSystemCounters.lagCount, sizeof(GBSystemCounters.lagCount)); 1.2550 + utilGzWrite(gzFile, &GBSystemCounters.lagged, sizeof(GBSystemCounters.lagged)); 1.2551 + utilGzWrite(gzFile, &GBSystemCounters.laggedLast, sizeof(GBSystemCounters.laggedLast)); 1.2552 + } 1.2553 + 1.2554 + return true; 1.2555 +} 1.2556 + 1.2557 +bool gbWriteMemSaveState(char *memory, int available) 1.2558 +{ 1.2559 + gzFile gzFile = utilMemGzOpen(memory, available, "w"); 1.2560 + 1.2561 + if (gzFile == NULL) 1.2562 + { 1.2563 + return false; 1.2564 + } 1.2565 + 1.2566 + bool res = gbWriteSaveStateToStream(gzFile); 1.2567 + 1.2568 + long pos = utilGzTell(gzFile) + 8; 1.2569 + 1.2570 + if (pos >= (available)) 1.2571 + res = false; 1.2572 + 1.2573 + utilGzClose(gzFile); 1.2574 + 1.2575 + return res; 1.2576 +} 1.2577 + 1.2578 +bool gbWriteSaveState(const char *name) 1.2579 +{ 1.2580 + gzFile gzFile = utilGzOpen(name, "wb"); 1.2581 + 1.2582 + if (gzFile == NULL) 1.2583 + return false; 1.2584 + 1.2585 + bool res = gbWriteSaveStateToStream(gzFile); 1.2586 + 1.2587 + utilGzClose(gzFile); 1.2588 + return res; 1.2589 +} 1.2590 + 1.2591 +static int tempStateID = 0; 1.2592 +static int tempFailCount = 0; 1.2593 +static bool backupSafe = true; 1.2594 + 1.2595 +bool gbReadSaveStateFromStream(gzFile gzFile) 1.2596 +{ 1.2597 + int type; 1.2598 + char tempBackupName [128]; 1.2599 + if (backupSafe) 1.2600 + { 1.2601 + sprintf(tempBackupName, "gbatempsave%d.sav", tempStateID++); 1.2602 + gbWriteSaveState(tempBackupName); 1.2603 + } 1.2604 + 1.2605 + int version = utilReadInt(gzFile); 1.2606 + 1.2607 + if (version > GBSAVE_GAME_VERSION || version < 0) 1.2608 + { 1.2609 + systemMessage(MSG_UNSUPPORTED_VB_SGM, 1.2610 + N_("Unsupported VisualBoy save game version %d"), version); 1.2611 + goto failedLoadGB; 1.2612 + } 1.2613 + 1.2614 + u8 romname[20]; 1.2615 + 1.2616 + utilGzRead(gzFile, romname, 15); 1.2617 + 1.2618 + if (memcmp(&gbRom[0x134], romname, 15) != 0) 1.2619 + { 1.2620 + systemMessage(MSG_CANNOT_LOAD_SGM_FOR, 1.2621 + N_("Cannot load save game for %s. Playing %s"), 1.2622 + romname, &gbRom[0x134]); 1.2623 + goto failedLoadGB; 1.2624 + } 1.2625 + 1.2626 + utilReadData(gzFile, gbSaveGameStruct); 1.2627 + 1.2628 + if (version >= GBSAVE_GAME_VERSION_7) 1.2629 + { 1.2630 + utilGzRead(gzFile, &IFF, 2); 1.2631 + } 1.2632 + 1.2633 + if (gbSgbMode) 1.2634 + { 1.2635 + gbSgbReadGame(gzFile, version); 1.2636 + } 1.2637 + else 1.2638 + { 1.2639 + gbSgbMask = 0; // loading a game at the wrong time causes no display 1.2640 + } 1.2641 + 1.2642 + utilGzRead(gzFile, &gbDataMBC1, sizeof(gbDataMBC1)); 1.2643 + utilGzRead(gzFile, &gbDataMBC2, sizeof(gbDataMBC2)); 1.2644 + if (version < GBSAVE_GAME_VERSION_4) 1.2645 + // prior to version 4, there was no adjustment for the time the game 1.2646 + // was last played, so we have less to read. This needs update if the 1.2647 + // structure changes again. 1.2648 + utilGzRead(gzFile, &gbDataMBC3, sizeof(int32) * 10); 1.2649 + else 1.2650 + { 1.2651 + //assert(sizeof(time_t) == 4); 1.2652 + utilGzRead(gzFile, &gbDataMBC3, sizeof(gbDataMBC3)); 1.2653 + } 1.2654 + utilGzRead(gzFile, &gbDataMBC5, sizeof(gbDataMBC5)); 1.2655 + utilGzRead(gzFile, &gbDataHuC1, sizeof(gbDataHuC1)); 1.2656 + utilGzRead(gzFile, &gbDataHuC3, sizeof(gbDataHuC3)); 1.2657 + 1.2658 + if (version >= GBSAVE_GAME_VERSION_12) 1.2659 + { 1.2660 + utilGzRead(gzFile, pix, 4 * 257 * 226); 1.2661 + } 1.2662 + else 1.2663 + { 1.2664 + memset(pix, 0, 257 * 226 * sizeof(u32)); 1.2665 +// if(version < GBSAVE_GAME_VERSION_5) 1.2666 +// utilGzRead(gzFile, pix, 256*224*sizeof(u16)); 1.2667 + } 1.2668 + 1.2669 + if (version < GBSAVE_GAME_VERSION_6) 1.2670 + { 1.2671 + utilGzRead(gzFile, gbPalette, 64 * sizeof(u16)); 1.2672 + } 1.2673 + else 1.2674 + utilGzRead(gzFile, gbPalette, 128 * sizeof(u16)); 1.2675 + 1.2676 + // todo: remove 1.2677 + utilGzRead(gzFile, gbPalette, 128 * sizeof(u16)); 1.2678 + 1.2679 + if (version < GBSAVE_GAME_VERSION_10) 1.2680 + { 1.2681 + if (!gbCgbMode && !gbSgbMode) 1.2682 + { 1.2683 + for (int i = 0; i < 8; i++) 1.2684 + gbPalette[i] = systemGbPalette[gbPaletteOption * 8 + i]; 1.2685 + } 1.2686 + } 1.2687 + 1.2688 + utilGzRead(gzFile, &gbMemory[0x8000], 0x8000); 1.2689 + 1.2690 + if (gbRamSize && gbRam) 1.2691 + { 1.2692 + utilGzRead(gzFile, gbRam, gbRamSize); 1.2693 + } 1.2694 + 1.2695 + gbMemoryMap[0x00] = &gbRom[0x0000]; 1.2696 + gbMemoryMap[0x01] = &gbRom[0x1000]; 1.2697 + gbMemoryMap[0x02] = &gbRom[0x2000]; 1.2698 + gbMemoryMap[0x03] = &gbRom[0x3000]; 1.2699 + gbMemoryMap[0x04] = &gbRom[0x4000]; 1.2700 + gbMemoryMap[0x05] = &gbRom[0x5000]; 1.2701 + gbMemoryMap[0x06] = &gbRom[0x6000]; 1.2702 + gbMemoryMap[0x07] = &gbRom[0x7000]; 1.2703 + gbMemoryMap[0x08] = &gbMemory[0x8000]; 1.2704 + gbMemoryMap[0x09] = &gbMemory[0x9000]; 1.2705 + gbMemoryMap[0x0a] = &gbMemory[0xa000]; 1.2706 + gbMemoryMap[0x0b] = &gbMemory[0xb000]; 1.2707 + gbMemoryMap[0x0c] = &gbMemory[0xc000]; 1.2708 + gbMemoryMap[0x0d] = &gbMemory[0xd000]; 1.2709 + gbMemoryMap[0x0e] = &gbMemory[0xe000]; 1.2710 + gbMemoryMap[0x0f] = &gbMemory[0xf000]; 1.2711 + 1.2712 + type = gbRom[0x147]; 1.2713 + 1.2714 + switch (type) 1.2715 + { 1.2716 + case 0x00: 1.2717 + case 0x01: 1.2718 + case 0x02: 1.2719 + case 0x03: 1.2720 + // MBC 1 1.2721 + memoryUpdateMapMBC1(); 1.2722 + break; 1.2723 + case 0x05: 1.2724 + case 0x06: 1.2725 + // MBC2 1.2726 + memoryUpdateMapMBC2(); 1.2727 + break; 1.2728 + case 0x0f: 1.2729 + case 0x10: 1.2730 + case 0x11: 1.2731 + case 0x12: 1.2732 + case 0x13: 1.2733 + // MBC 3 1.2734 + memoryUpdateMapMBC3(); 1.2735 + break; 1.2736 + case 0x19: 1.2737 + case 0x1a: 1.2738 + case 0x1b: 1.2739 + // MBC5 1.2740 + memoryUpdateMapMBC5(); 1.2741 + break; 1.2742 + case 0x1c: 1.2743 + case 0x1d: 1.2744 + case 0x1e: 1.2745 + // MBC 5 Rumble 1.2746 + memoryUpdateMapMBC5(); 1.2747 + break; 1.2748 + case 0x22: 1.2749 + // MBC 7 1.2750 + memoryUpdateMapMBC7(); 1.2751 + break; 1.2752 + case 0xfe: 1.2753 + // HuC3 1.2754 + memoryUpdateMapHuC3(); 1.2755 + break; 1.2756 + case 0xff: 1.2757 + // HuC1 1.2758 + memoryUpdateMapHuC1(); 1.2759 + break; 1.2760 + } 1.2761 + 1.2762 + if (gbCgbMode) 1.2763 + { 1.2764 + if (!gbVram) 1.2765 + gbVram = (u8 *)malloc(0x4000 + 4); 1.2766 + if (!gbWram) 1.2767 + gbWram = (u8 *)malloc(0x8000 + 4); 1.2768 + utilGzRead(gzFile, gbVram, 0x4000); 1.2769 + utilGzRead(gzFile, gbWram, 0x8000); 1.2770 + 1.2771 + int value = register_SVBK; 1.2772 + if (value == 0) 1.2773 + value = 1; 1.2774 + 1.2775 + gbMemoryMap[0x08] = &gbVram[register_VBK * 0x2000]; 1.2776 + gbMemoryMap[0x09] = &gbVram[register_VBK * 0x2000 + 0x1000]; 1.2777 + gbMemoryMap[0x0d] = &gbWram[value * 0x1000]; 1.2778 + } 1.2779 + else 1.2780 + { 1.2781 + if (gbVram) 1.2782 + { 1.2783 + free(gbVram); 1.2784 + gbVram = NULL; 1.2785 + } 1.2786 + if (gbWram) 1.2787 + { 1.2788 + free(gbWram); 1.2789 + gbWram = NULL; 1.2790 + } 1.2791 + } 1.2792 + 1.2793 + gbSoundReadGame(version, gzFile); 1.2794 + 1.2795 +#if 0 1.2796 + if (gbBorderOn) 1.2797 + { 1.2798 + gbSgbRenderBorder(); 1.2799 + } 1.2800 + 1.2801 + systemRefreshScreen(); 1.2802 +#endif 1.2803 + 1.2804 + if (version > GBSAVE_GAME_VERSION_1) 1.2805 + gbCheatsReadGame(gzFile, version); 1.2806 + 1.2807 + systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED; 1.2808 + 1.2809 + if (version >= GBSAVE_GAME_VERSION_11) // new to re-recording version: 1.2810 + { 1.2811 + extern int32 sensorX, sensorY; // from SDL.cpp 1.2812 + utilGzRead(gzFile, &sensorX, sizeof(sensorX)); 1.2813 + utilGzRead(gzFile, &sensorY, sizeof(sensorY)); 1.2814 + utilGzRead(gzFile, gbJoymask, 4 * sizeof(*gbJoymask)); // this has to be saved or old input will incorrectly get carried 1.2815 + // back on loading a snapshot! 1.2816 + 1.2817 + bool8 movieSnapshot; 1.2818 + utilGzRead(gzFile, &movieSnapshot, sizeof(movieSnapshot)); 1.2819 + if (VBAMovieActive() && !movieSnapshot) 1.2820 + { 1.2821 + systemMessage(0, N_("Can't load a non-movie snapshot while a movie is active.")); 1.2822 + goto failedLoadGB; 1.2823 + } 1.2824 + 1.2825 + if (movieSnapshot) // even if a movie isn't active we still want to parse through this in case other stuff is added 1.2826 + // later on in the save format 1.2827 + { 1.2828 + uint32 movieInputDataSize = 0; 1.2829 + utilGzRead(gzFile, &movieInputDataSize, sizeof(movieInputDataSize)); 1.2830 + uint8 *local_movie_data = new uint8 [movieInputDataSize]; 1.2831 + int readBytes = utilGzRead(gzFile, local_movie_data, movieInputDataSize); 1.2832 + if (readBytes != movieInputDataSize) 1.2833 + { 1.2834 + systemMessage(0, N_("Corrupt movie snapshot.")); 1.2835 + if (local_movie_data) 1.2836 + delete [] local_movie_data; 1.2837 + goto failedLoadGB; 1.2838 + } 1.2839 + int code = VBAMovieUnfreeze(local_movie_data, movieInputDataSize); 1.2840 + if (local_movie_data) 1.2841 + delete [] local_movie_data; 1.2842 + if (code != MOVIE_SUCCESS && VBAMovieActive()) 1.2843 + { 1.2844 + char errStr [1024]; 1.2845 + strcpy(errStr, "Failed to load movie snapshot"); 1.2846 + switch (code) 1.2847 + { 1.2848 + case MOVIE_NOT_FROM_THIS_MOVIE: 1.2849 + strcat(errStr, ";\nSnapshot not from this movie"); break; 1.2850 + case MOVIE_NOT_FROM_A_MOVIE: 1.2851 + strcat(errStr, ";\nNot a movie snapshot"); break; // shouldn't get here... 1.2852 + case MOVIE_SNAPSHOT_INCONSISTENT: 1.2853 + strcat(errStr, ";\nSnapshot inconsistent with movie"); break; 1.2854 + case MOVIE_WRONG_FORMAT: 1.2855 + strcat(errStr, ";\nWrong format"); break; 1.2856 + } 1.2857 + strcat(errStr, "."); 1.2858 + systemMessage(0, N_(errStr)); 1.2859 + goto failedLoadGB; 1.2860 + } 1.2861 + } 1.2862 + utilGzRead(gzFile, &GBSystemCounters.frameCount, sizeof(GBSystemCounters.frameCount)); 1.2863 + } 1.2864 + 1.2865 + if (version >= GBSAVE_GAME_VERSION_13) // new to rerecording 19.4 wip (svn r22+): 1.2866 + { 1.2867 + utilGzRead(gzFile, &GBSystemCounters.lagCount, sizeof(GBSystemCounters.lagCount)); 1.2868 + utilGzRead(gzFile, &GBSystemCounters.lagged, sizeof(GBSystemCounters.lagged)); 1.2869 + utilGzRead(gzFile, &GBSystemCounters.laggedLast, sizeof(GBSystemCounters.laggedLast)); 1.2870 + } 1.2871 + 1.2872 + if (backupSafe) 1.2873 + { 1.2874 + remove(tempBackupName); 1.2875 + tempFailCount = 0; 1.2876 + } 1.2877 + 1.2878 + for (int i = 0; i < 4; ++i) 1.2879 + systemSetJoypad(i, gbJoymask[i] & 0xFFFF); 1.2880 + 1.2881 + // FIXME: horrible kludge 1.2882 + memcpy(s_gbJoymask, gbJoymask, sizeof(gbJoymask)); 1.2883 + 1.2884 + VBAUpdateButtonPressDisplay(); 1.2885 + VBAUpdateFrameCountDisplay(); 1.2886 + systemRefreshScreen(); 1.2887 + return true; 1.2888 + 1.2889 +failedLoadGB: 1.2890 + if (backupSafe) 1.2891 + { 1.2892 + tempFailCount++; 1.2893 + if (tempFailCount < 3) // fail no more than 2 times in a row 1.2894 + gbReadSaveState(tempBackupName); 1.2895 + remove(tempBackupName); 1.2896 + } 1.2897 + return false; 1.2898 +} 1.2899 + 1.2900 +bool gbReadMemSaveState(char *memory, int available) 1.2901 +{ 1.2902 + gzFile gzFile = utilMemGzOpen(memory, available, "r"); 1.2903 + 1.2904 + backupSafe = false; 1.2905 + bool res = gbReadSaveStateFromStream(gzFile); 1.2906 + backupSafe = true; 1.2907 + 1.2908 + utilGzClose(gzFile); 1.2909 + 1.2910 + return res; 1.2911 +} 1.2912 + 1.2913 +bool gbReadSaveState(const char *name) 1.2914 +{ 1.2915 + gzFile gzFile = utilGzOpen(name, "rb"); 1.2916 + 1.2917 + if (gzFile == NULL) 1.2918 + { 1.2919 + return false; 1.2920 + } 1.2921 + 1.2922 + bool res = gbReadSaveStateFromStream(gzFile); 1.2923 + 1.2924 + utilGzClose(gzFile); 1.2925 + 1.2926 + return res; 1.2927 +} 1.2928 + 1.2929 +bool gbWritePNGFile(const char *fileName) 1.2930 +{ 1.2931 + if (gbBorderOn) 1.2932 + return utilWritePNGFile(fileName, 256, 224, pix); 1.2933 + return utilWritePNGFile(fileName, 160, 144, pix); 1.2934 +} 1.2935 + 1.2936 +bool gbWriteBMPFile(const char *fileName) 1.2937 +{ 1.2938 + if (gbBorderOn) 1.2939 + return utilWriteBMPFile(fileName, 256, 224, pix); 1.2940 + return utilWriteBMPFile(fileName, 160, 144, pix); 1.2941 +} 1.2942 + 1.2943 +void gbCleanUp() 1.2944 +{ 1.2945 + newFrame = true; 1.2946 + 1.2947 + GBSystemCounters.frameCount = 0; 1.2948 + GBSystemCounters.lagCount = 0; 1.2949 + GBSystemCounters.extraCount = 0; 1.2950 + GBSystemCounters.lagged = true; 1.2951 + GBSystemCounters.laggedLast = true; 1.2952 + 1.2953 + if (gbRam != NULL) 1.2954 + { 1.2955 + free(gbRam); 1.2956 + gbRam = NULL; 1.2957 + } 1.2958 + 1.2959 + if (gbRom != NULL) 1.2960 + { 1.2961 + free(gbRom); 1.2962 + gbRom = NULL; 1.2963 + } 1.2964 + 1.2965 + if (gbMemory != NULL) 1.2966 + { 1.2967 + free(gbMemory); 1.2968 + gbMemory = NULL; 1.2969 + } 1.2970 + 1.2971 + if (gbLineBuffer != NULL) 1.2972 + { 1.2973 + free(gbLineBuffer); 1.2974 + gbLineBuffer = NULL; 1.2975 + } 1.2976 + 1.2977 + if (origPix != NULL) 1.2978 + { 1.2979 + free(origPix); 1.2980 + origPix = NULL; 1.2981 + } 1.2982 + pix = NULL; 1.2983 + 1.2984 + gbSgbShutdown(); 1.2985 + 1.2986 + if (gbVram != NULL) 1.2987 + { 1.2988 + free(gbVram); 1.2989 + gbVram = NULL; 1.2990 + } 1.2991 + 1.2992 + if (gbWram != NULL) 1.2993 + { 1.2994 + free(gbWram); 1.2995 + gbWram = NULL; 1.2996 + } 1.2997 + 1.2998 + systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED; 1.2999 + 1.3000 + memset(gbJoymask, 0, sizeof(gbJoymask)); 1.3001 + // FIXME: horrible kludge 1.3002 + memset(s_gbJoymask, 0, sizeof(s_gbJoymask)); 1.3003 + 1.3004 + systemClearJoypads(); 1.3005 + systemResetSensor(); 1.3006 + 1.3007 +// gbLastTime = gbFrameCount = 0; 1.3008 + systemRefreshScreen(); 1.3009 +} 1.3010 + 1.3011 +bool gbLoadRom(const char *szFile) 1.3012 +{ 1.3013 + int size = 0; 1.3014 + 1.3015 + if (gbRom != NULL) 1.3016 + { 1.3017 + gbCleanUp(); 1.3018 + } 1.3019 + 1.3020 + systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED; 1.3021 + 1.3022 + gbRom = utilLoad(szFile, 1.3023 + utilIsGBImage, 1.3024 + NULL, 1.3025 + size); 1.3026 + if (!gbRom) 1.3027 + return false; 1.3028 + 1.3029 + gbRomSize = size; 1.3030 + 1.3031 + return gbUpdateSizes(); 1.3032 +} 1.3033 + 1.3034 +bool gbUpdateSizes() 1.3035 +{ 1.3036 + if (gbRom[0x148] > 8) 1.3037 + { 1.3038 + systemMessage(MSG_UNSUPPORTED_ROM_SIZE, 1.3039 + N_("Unsupported rom size %02x"), gbRom[0x148]); 1.3040 + return false; 1.3041 + } 1.3042 + 1.3043 + if (gbRomSize < gbRomSizes[gbRom[0x148]]) 1.3044 + { 1.3045 + gbRom = (u8 *)realloc(gbRom, gbRomSizes[gbRom[0x148]]); 1.3046 + } 1.3047 + gbRomSize = gbRomSizes[gbRom[0x148]]; 1.3048 + gbRomSizeMask = gbRomSizesMasks[gbRom[0x148]]; 1.3049 + 1.3050 + if (gbRom[0x149] > 5) 1.3051 + { 1.3052 + systemMessage(MSG_UNSUPPORTED_RAM_SIZE, 1.3053 + N_("Unsupported ram size %02x"), gbRom[0x149]); 1.3054 + return false; 1.3055 + } 1.3056 + 1.3057 + gbRamSize = gbRamSizes[gbRom[0x149]]; 1.3058 + gbRamSizeMask = gbRamSizesMasks[gbRom[0x149]]; 1.3059 + 1.3060 + if (gbRamSize) 1.3061 + { 1.3062 + gbRam = (u8 *)malloc(gbRamSize + 4); 1.3063 + memset(gbRam, 0xFF, gbRamSize + 4); 1.3064 + } 1.3065 + 1.3066 + int type = gbRom[0x147]; 1.3067 + 1.3068 + mapperReadRAM = NULL; 1.3069 + 1.3070 + switch (type) 1.3071 + { 1.3072 + case 0x00: 1.3073 + case 0x01: 1.3074 + case 0x02: 1.3075 + case 0x03: 1.3076 + // MBC 1 1.3077 + mapper = mapperMBC1ROM; 1.3078 + mapperRAM = mapperMBC1RAM; 1.3079 + break; 1.3080 + case 0x05: 1.3081 + case 0x06: 1.3082 + // MBC2 1.3083 + mapper = mapperMBC2ROM; 1.3084 + mapperRAM = mapperMBC2RAM; 1.3085 + gbRamSize = 0x200; 1.3086 + gbRamSizeMask = 0x1ff; 1.3087 + break; 1.3088 + case 0x0f: 1.3089 + case 0x10: 1.3090 + case 0x11: 1.3091 + case 0x12: 1.3092 + case 0x13: 1.3093 + // MBC 3 1.3094 + mapper = mapperMBC3ROM; 1.3095 + mapperRAM = mapperMBC3RAM; 1.3096 + mapperReadRAM = mapperMBC3ReadRAM; 1.3097 + break; 1.3098 + case 0x19: 1.3099 + case 0x1a: 1.3100 + case 0x1b: 1.3101 + // MBC5 1.3102 + mapper = mapperMBC5ROM; 1.3103 + mapperRAM = mapperMBC5RAM; 1.3104 + break; 1.3105 + case 0x1c: 1.3106 + case 0x1d: 1.3107 + case 0x1e: 1.3108 + // MBC 5 Rumble 1.3109 + mapper = mapperMBC5ROM; 1.3110 + mapperRAM = mapperMBC5RAM; 1.3111 + break; 1.3112 + case 0x22: 1.3113 + // MBC 7 1.3114 + mapper = mapperMBC7ROM; 1.3115 + mapperRAM = mapperMBC7RAM; 1.3116 + mapperReadRAM = mapperMBC7ReadRAM; 1.3117 + break; 1.3118 + case 0xfe: 1.3119 + // HuC3 1.3120 + mapper = mapperHuC3ROM; 1.3121 + mapperRAM = mapperHuC3RAM; 1.3122 + mapperReadRAM = mapperHuC3ReadRAM; 1.3123 + break; 1.3124 + case 0xff: 1.3125 + // HuC1 1.3126 + mapper = mapperHuC1ROM; 1.3127 + mapperRAM = mapperHuC1RAM; 1.3128 + break; 1.3129 + default: 1.3130 + systemMessage(MSG_UNKNOWN_CARTRIDGE_TYPE, 1.3131 + N_("Unknown cartridge type %02x"), type); 1.3132 + return false; 1.3133 + } 1.3134 + 1.3135 + switch (type) 1.3136 + { 1.3137 + case 0x03: 1.3138 + case 0x06: 1.3139 + case 0x0f: 1.3140 + case 0x10: 1.3141 + case 0x13: 1.3142 + case 0x1b: 1.3143 + case 0x1d: 1.3144 + case 0x1e: 1.3145 + case 0x22: 1.3146 + case 0xff: 1.3147 + gbBattery = 1; 1.3148 + break; 1.3149 + } 1.3150 + 1.3151 + gbInit(); 1.3152 + gbReset(); 1.3153 + 1.3154 + return true; 1.3155 +} 1.3156 + 1.3157 +void gbEmulate(int ticksToStop) 1.3158 +{ 1.3159 + gbRegister tempRegister; 1.3160 + u8 tempValue; 1.3161 + s8 offset; 1.3162 + 1.3163 + int clockTicks = 0; 1.3164 + gbDmaTicks = 0; 1.3165 + 1.3166 + register int opcode = 0; 1.3167 + 1.3168 + u32 newmask = 0; 1.3169 + if (newFrame) 1.3170 + { 1.3171 + extern void VBAOnExitingFrameBoundary(); 1.3172 + VBAOnExitingFrameBoundary(); 1.3173 + 1.3174 + // update joystick information 1.3175 + systemReadJoypads(); 1.3176 + 1.3177 + bool sensor = (gbRom[0x147] == 0x22); 1.3178 + 1.3179 + // read joystick 1.3180 + if (gbSgbMode && gbSgbMultiplayer) 1.3181 + { 1.3182 + if (gbSgbFourPlayers) 1.3183 + { 1.3184 + gbJoymask[0] = systemGetJoypad(0, sensor); 1.3185 + gbJoymask[1] = systemGetJoypad(1, false); 1.3186 + gbJoymask[2] = systemGetJoypad(2, false); 1.3187 + gbJoymask[3] = systemGetJoypad(3, false); 1.3188 + } 1.3189 + else 1.3190 + { 1.3191 + gbJoymask[0] = systemGetJoypad(0, sensor); 1.3192 + gbJoymask[1] = systemGetJoypad(1, false); 1.3193 + } 1.3194 + } 1.3195 + else 1.3196 + { 1.3197 + gbJoymask[0] = systemGetJoypad(0, sensor); 1.3198 + } 1.3199 + 1.3200 + // FIXME: horrible kludge 1.3201 + memcpy(s_gbJoymask, gbJoymask, sizeof(gbJoymask)); 1.3202 + 1.3203 +// if (sensor) 1.3204 +// systemUpdateMotionSensor(0); 1.3205 + 1.3206 + newmask = gbJoymask[0]; 1.3207 + if (newmask & 0xFF) 1.3208 + { 1.3209 + gbInterrupt |= 16; 1.3210 + } 1.3211 + 1.3212 + extButtons = (newmask >> 18); 1.3213 + speedup = (extButtons & 1) != 0; 1.3214 + 1.3215 + VBAMovieResetIfRequested(); 1.3216 + 1.3217 + CallRegisteredLuaFunctions(LUACALL_BEFOREEMULATION); 1.3218 + 1.3219 + newFrame = false; 1.3220 + } 1.3221 + 1.3222 + for (;; ) 1.3223 + { 1.3224 +#ifndef FINAL_VERSION 1.3225 + if (systemDebug) 1.3226 + { 1.3227 + if (!(IFF & 0x80)) 1.3228 + { 1.3229 + if (systemDebug > 1) 1.3230 + { 1.3231 + sprintf(gbBuffer, "PC=%04x AF=%04x BC=%04x DE=%04x HL=%04x SP=%04x I=%04x\n", 1.3232 + PC.W, AF.W, BC.W, DE.W, HL.W, SP.W, IFF); 1.3233 + } 1.3234 + else 1.3235 + { 1.3236 + sprintf(gbBuffer, "PC=%04x I=%02x\n", PC.W, IFF); 1.3237 + } 1.3238 + log(gbBuffer); 1.3239 + } 1.3240 + } 1.3241 +#endif 1.3242 + if (IFF & 0x80) 1.3243 + { 1.3244 + if (register_LCDC & 0x80) 1.3245 + { 1.3246 + clockTicks = gbLcdTicks; 1.3247 + } 1.3248 + else 1.3249 + clockTicks = 100; 1.3250 + 1.3251 + if (gbLcdMode == 1 && (gbLcdLYIncrementTicks < clockTicks)) 1.3252 + clockTicks = gbLcdLYIncrementTicks; 1.3253 + 1.3254 + if (gbSerialOn && (gbSerialTicks < clockTicks)) 1.3255 + clockTicks = gbSerialTicks; 1.3256 + 1.3257 + if (gbTimerOn && (gbTimerTicks < clockTicks)) 1.3258 + clockTicks = gbTimerTicks; 1.3259 + 1.3260 + if (soundTicks && (soundTicks < clockTicks)) 1.3261 + clockTicks = soundTicks; 1.3262 + } 1.3263 + else 1.3264 + { 1.3265 + opcode = gbReadOpcode(PC.W); 1.3266 + CallRegisteredLuaMemHook(PC.W, 1, opcode, LUAMEMHOOK_EXEC); 1.3267 + PC.W++; 1.3268 + 1.3269 + if (IFF & 0x100) 1.3270 + { 1.3271 + IFF &= 0xff; 1.3272 + PC.W--; 1.3273 + } 1.3274 + 1.3275 + clockTicks = gbCycles[opcode]; 1.3276 + 1.3277 + switch (opcode) 1.3278 + { 1.3279 + case 0xCB: 1.3280 + // extended opcode 1.3281 + //CallRegisteredLuaMemHook(PC.W, 1, opcode, LUAMEMHOOK_EXEC); // is this desired? 1.3282 + opcode = gbReadOpcode(PC.W++); 1.3283 + clockTicks = gbCyclesCB[opcode]; 1.3284 + switch (opcode) 1.3285 + { 1.3286 +#include "gbCodesCB.h" 1.3287 + } 1.3288 + break; 1.3289 +#include "gbCodes.h" 1.3290 + } 1.3291 + } 1.3292 + 1.3293 + if (!emulating) 1.3294 + return; 1.3295 + 1.3296 + if (gbDmaTicks) 1.3297 + { 1.3298 + clockTicks += gbDmaTicks; 1.3299 + gbDmaTicks = 0; 1.3300 + } 1.3301 + 1.3302 + if (gbSgbMode) 1.3303 + { 1.3304 + if (gbSgbPacketTimeout) 1.3305 + { 1.3306 + gbSgbPacketTimeout -= clockTicks; 1.3307 + 1.3308 + if (gbSgbPacketTimeout <= 0) 1.3309 + gbSgbResetPacketState(); 1.3310 + } 1.3311 + } 1.3312 + 1.3313 + ticksToStop -= clockTicks; 1.3314 + 1.3315 + // DIV register emulation 1.3316 + gbDivTicks -= clockTicks; 1.3317 + while (gbDivTicks <= 0) 1.3318 + { 1.3319 + register_DIV++; 1.3320 + gbDivTicks += GBDIV_CLOCK_TICKS; 1.3321 + } 1.3322 + 1.3323 + if (register_LCDC & 0x80) 1.3324 + { 1.3325 + // LCD stuff 1.3326 + gbLcdTicks -= clockTicks; 1.3327 + if (gbLcdMode == 1) 1.3328 + { 1.3329 + // during V-BLANK,we need to increment LY at the same rate! 1.3330 + gbLcdLYIncrementTicks -= clockTicks; 1.3331 + while (gbLcdLYIncrementTicks <= 0) 1.3332 + { 1.3333 + gbLcdLYIncrementTicks += GBLY_INCREMENT_CLOCK_TICKS; 1.3334 + 1.3335 + if (register_LY < 153) 1.3336 + { 1.3337 + register_LY++; 1.3338 + 1.3339 + gbCompareLYToLYC(); 1.3340 + 1.3341 + if (register_LY >= 153) 1.3342 + gbLcdLYIncrementTicks = 6; 1.3343 + } 1.3344 + else 1.3345 + { 1.3346 + register_LY = 0x00; 1.3347 + // reset the window line 1.3348 + gbWindowLine = -1; 1.3349 + gbLcdLYIncrementTicks = GBLY_INCREMENT_CLOCK_TICKS * 2; 1.3350 + gbCompareLYToLYC(); 1.3351 + } 1.3352 + } 1.3353 + } 1.3354 + 1.3355 + // our counter is off, see what we need to do 1.3356 + while (gbLcdTicks <= 0) 1.3357 + { 1.3358 + int framesToSkip = systemFramesToSkip(); 1.3359 + 1.3360 + switch (gbLcdMode) 1.3361 + { 1.3362 + case 0: 1.3363 + // H-Blank 1.3364 + register_LY++; 1.3365 + 1.3366 + gbCompareLYToLYC(); 1.3367 + 1.3368 + // check if we reached the V-Blank period 1.3369 + if (register_LY == 144) 1.3370 + { 1.3371 + // Yes, V-Blank 1.3372 + // set the LY increment counter 1.3373 + gbLcdLYIncrementTicks = gbLcdTicks + GBLY_INCREMENT_CLOCK_TICKS; 1.3374 + gbLcdTicks += GBLCD_MODE_1_CLOCK_TICKS; 1.3375 + gbLcdMode = 1; 1.3376 + if (register_LCDC & 0x80) 1.3377 + { 1.3378 + gbInterrupt |= 1; // V-Blank interrupt 1.3379 + gbInterruptWait = 6; 1.3380 + if (register_STAT & 0x10) 1.3381 + gbInterrupt |= 2; 1.3382 + } 1.3383 + 1.3384 + systemFrame(); 1.3385 + 1.3386 + ++gbFrameCount; 1.3387 + u32 currentTime = systemGetClock(); 1.3388 + if (currentTime - gbLastTime >= 1000) 1.3389 + { 1.3390 + systemShowSpeed(int(float(gbFrameCount) * 100000 / (float(currentTime - gbLastTime) * 60) + .5f)); 1.3391 + gbLastTime = currentTime; 1.3392 + gbFrameCount = 0; 1.3393 + } 1.3394 + 1.3395 + ++GBSystemCounters.frameCount; 1.3396 + if (GBSystemCounters.lagged) 1.3397 + { 1.3398 + ++GBSystemCounters.lagCount; 1.3399 + } 1.3400 + GBSystemCounters.laggedLast = GBSystemCounters.lagged; 1.3401 + GBSystemCounters.lagged = true; 1.3402 + 1.3403 + extern void VBAOnEnteringFrameBoundary(); 1.3404 + VBAOnEnteringFrameBoundary(); 1.3405 + 1.3406 + newFrame = true; 1.3407 + 1.3408 + pauseAfterFrameAdvance = systemPauseOnFrame(); 1.3409 + 1.3410 + if (gbFrameSkipCount >= framesToSkip || pauseAfterFrameAdvance) 1.3411 + { 1.3412 + if (gbBorderOn) 1.3413 + gbSgbRenderBorder(); // clear unnecessary things on border (e.g. in-game text message) 1.3414 + 1.3415 + systemRenderFrame(); 1.3416 + gbFrameSkipCount = 0; 1.3417 + 1.3418 + bool capturePressed = (extButtons & 2) != 0; 1.3419 + if (capturePressed && !capturePrevious) 1.3420 + { 1.3421 + captureNumber = systemScreenCapture(captureNumber); 1.3422 + } 1.3423 + capturePrevious = capturePressed && !pauseAfterFrameAdvance; 1.3424 + } 1.3425 + else 1.3426 + { 1.3427 + ++gbFrameSkipCount; 1.3428 + } 1.3429 + 1.3430 + if (pauseAfterFrameAdvance) 1.3431 + { 1.3432 + systemSetPause(true); 1.3433 + } 1.3434 + } 1.3435 + else 1.3436 + { 1.3437 + // go the the OAM being accessed mode 1.3438 + gbLcdTicks += GBLCD_MODE_2_CLOCK_TICKS; 1.3439 + gbLcdMode = 2; 1.3440 + 1.3441 + // only one LCD interrupt per line. may need to generalize... 1.3442 + if (!(register_STAT & 0x40) || 1.3443 + (register_LY != register_LYC)) 1.3444 + { 1.3445 + if ((register_STAT & 0x28) == 0x20) 1.3446 + gbInterrupt |= 2; 1.3447 + } 1.3448 + } 1.3449 + 1.3450 + break; 1.3451 + case 1: 1.3452 + // V-Blank 1.3453 + // next mode is OAM being accessed mode 1.3454 + gbLcdTicks += GBLCD_MODE_2_CLOCK_TICKS; 1.3455 + gbLcdMode = 2; 1.3456 + if (!(register_STAT & 0x40) || 1.3457 + (register_LY != register_LYC)) 1.3458 + { 1.3459 + if ((register_STAT & 0x28) == 0x20) 1.3460 + gbInterrupt |= 2; 1.3461 + } 1.3462 + break; 1.3463 + case 2: 1.3464 + // OAM being accessed mode 1.3465 + 1.3466 + // next mode is OAM and VRAM in use 1.3467 + gbLcdTicks += GBLCD_MODE_3_CLOCK_TICKS; 1.3468 + gbLcdMode = 3; 1.3469 + break; 1.3470 + case 3: 1.3471 + // OAM and VRAM in use 1.3472 + // next mode is H-Blank 1.3473 + if (register_LY < 144) 1.3474 + { 1.3475 + if (!gbSgbMask) 1.3476 + { 1.3477 + if (gbFrameSkipCount >= framesToSkip || pauseAfterFrameAdvance) 1.3478 + { 1.3479 + gbRenderLine(); 1.3480 + gbDrawSprites(); 1.3481 + 1.3482 + switch (systemColorDepth) 1.3483 + { 1.3484 + case 16: 1.3485 + 1.3486 + { 1.3487 + u16 *dest = (u16 *)pix + 1.3488 + (gbBorderLineSkip + 2) * (register_LY + gbBorderRowSkip + 1) 1.3489 + + gbBorderColumnSkip; 1.3490 + for (int x = 0; x < 160; ) 1.3491 + { 1.3492 + *dest++ = systemColorMap16[gbLineMix[x++]]; 1.3493 + *dest++ = systemColorMap16[gbLineMix[x++]]; 1.3494 + *dest++ = systemColorMap16[gbLineMix[x++]]; 1.3495 + *dest++ = systemColorMap16[gbLineMix[x++]]; 1.3496 + 1.3497 + *dest++ = systemColorMap16[gbLineMix[x++]]; 1.3498 + *dest++ = systemColorMap16[gbLineMix[x++]]; 1.3499 + *dest++ = systemColorMap16[gbLineMix[x++]]; 1.3500 + *dest++ = systemColorMap16[gbLineMix[x++]]; 1.3501 + 1.3502 + *dest++ = systemColorMap16[gbLineMix[x++]]; 1.3503 + *dest++ = systemColorMap16[gbLineMix[x++]]; 1.3504 + *dest++ = systemColorMap16[gbLineMix[x++]]; 1.3505 + *dest++ = systemColorMap16[gbLineMix[x++]]; 1.3506 + 1.3507 + *dest++ = systemColorMap16[gbLineMix[x++]]; 1.3508 + *dest++ = systemColorMap16[gbLineMix[x++]]; 1.3509 + *dest++ = systemColorMap16[gbLineMix[x++]]; 1.3510 + *dest++ = systemColorMap16[gbLineMix[x++]]; 1.3511 + } 1.3512 + if (gbBorderOn) 1.3513 + dest += gbBorderColumnSkip; 1.3514 + *dest++ = 0; // for filters that read one pixel more 1.3515 + break; 1.3516 + } 1.3517 + case 24: 1.3518 + 1.3519 + { 1.3520 + u8 *dest = (u8 *)pix + 1.3521 + 3 * (gbBorderLineSkip * (register_LY + gbBorderRowSkip) + 1.3522 + gbBorderColumnSkip); 1.3523 + for (int x = 0; x < 160; ) 1.3524 + { 1.3525 + *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; 1.3526 + dest += 3; 1.3527 + *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; 1.3528 + dest += 3; 1.3529 + *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; 1.3530 + dest += 3; 1.3531 + *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; 1.3532 + dest += 3; 1.3533 + 1.3534 + *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; 1.3535 + dest += 3; 1.3536 + *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; 1.3537 + dest += 3; 1.3538 + *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; 1.3539 + dest += 3; 1.3540 + *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; 1.3541 + dest += 3; 1.3542 + 1.3543 + *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; 1.3544 + dest += 3; 1.3545 + *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; 1.3546 + dest += 3; 1.3547 + *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; 1.3548 + dest += 3; 1.3549 + *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; 1.3550 + dest += 3; 1.3551 + 1.3552 + *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; 1.3553 + dest += 3; 1.3554 + *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; 1.3555 + dest += 3; 1.3556 + *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; 1.3557 + dest += 3; 1.3558 + *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; 1.3559 + dest += 3; 1.3560 + } 1.3561 + break; 1.3562 + } 1.3563 + case 32: 1.3564 + 1.3565 + { 1.3566 + u32 *dest = (u32 *)pix + 1.3567 + (gbBorderLineSkip + 1) * (register_LY + gbBorderRowSkip + 1) 1.3568 + + gbBorderColumnSkip; 1.3569 + for (int x = 0; x < 160; ) 1.3570 + { 1.3571 + *dest++ = systemColorMap32[gbLineMix[x++]]; 1.3572 + *dest++ = systemColorMap32[gbLineMix[x++]]; 1.3573 + *dest++ = systemColorMap32[gbLineMix[x++]]; 1.3574 + *dest++ = systemColorMap32[gbLineMix[x++]]; 1.3575 + 1.3576 + *dest++ = systemColorMap32[gbLineMix[x++]]; 1.3577 + *dest++ = systemColorMap32[gbLineMix[x++]]; 1.3578 + *dest++ = systemColorMap32[gbLineMix[x++]]; 1.3579 + *dest++ = systemColorMap32[gbLineMix[x++]]; 1.3580 + 1.3581 + *dest++ = systemColorMap32[gbLineMix[x++]]; 1.3582 + *dest++ = systemColorMap32[gbLineMix[x++]]; 1.3583 + *dest++ = systemColorMap32[gbLineMix[x++]]; 1.3584 + *dest++ = systemColorMap32[gbLineMix[x++]]; 1.3585 + 1.3586 + *dest++ = systemColorMap32[gbLineMix[x++]]; 1.3587 + *dest++ = systemColorMap32[gbLineMix[x++]]; 1.3588 + *dest++ = systemColorMap32[gbLineMix[x++]]; 1.3589 + *dest++ = systemColorMap32[gbLineMix[x++]]; 1.3590 + } 1.3591 + break; 1.3592 + } 1.3593 + } 1.3594 + } 1.3595 + } 1.3596 + } 1.3597 + gbLcdTicks += GBLCD_MODE_0_CLOCK_TICKS; 1.3598 + gbLcdMode = 0; 1.3599 + // only one LCD interrupt per line. may need to generalize... 1.3600 + if (!(register_STAT & 0x40) || 1.3601 + (register_LY != register_LYC)) 1.3602 + { 1.3603 + if (register_STAT & 0x08) 1.3604 + gbInterrupt |= 2; 1.3605 + } 1.3606 + if (gbHdmaOn) 1.3607 + { 1.3608 + gbDoHdma(); 1.3609 + } 1.3610 + break; 1.3611 + } 1.3612 + // mark the correct lcd mode on STAT register 1.3613 + register_STAT = (register_STAT & 0xfc) | gbLcdMode; 1.3614 + } 1.3615 + } 1.3616 + 1.3617 + // serial emulation 1.3618 + if (gbSerialOn) 1.3619 + { 1.3620 +#ifdef LINK_EMULATION 1.3621 + if (linkConnected) 1.3622 + { 1.3623 + gbSerialTicks -= clockTicks; 1.3624 + 1.3625 + while (gbSerialTicks <= 0) 1.3626 + { 1.3627 + // increment number of shifted bits 1.3628 + gbSerialBits++; 1.3629 + linkProc(); 1.3630 + if (gbSerialOn && (gbMemory[0xff02] & 1)) 1.3631 + { 1.3632 + if (gbSerialBits == 8) 1.3633 + { 1.3634 + gbSerialBits = 0; 1.3635 + gbMemory[0xff01] = 0xff; 1.3636 + gbMemory[0xff02] &= 0x7f; 1.3637 + gbSerialOn = 0; 1.3638 + gbInterrupt |= 8; 1.3639 + gbSerialTicks = 0; 1.3640 + } 1.3641 + } 1.3642 + gbSerialTicks += GBSERIAL_CLOCK_TICKS; 1.3643 + } 1.3644 + } 1.3645 + else 1.3646 + { 1.3647 +#endif 1.3648 + if (gbMemory[0xff02] & 1) 1.3649 + { 1.3650 + gbSerialTicks -= clockTicks; 1.3651 + 1.3652 + // overflow 1.3653 + while (gbSerialTicks <= 0) 1.3654 + { 1.3655 + // shift serial byte to right and put a 1 bit in its place 1.3656 + // gbMemory[0xff01] = 0x80 | (gbMemory[0xff01]>>1); 1.3657 + // increment number of shifted bits 1.3658 + gbSerialBits++; 1.3659 + if (gbSerialBits == 8) 1.3660 + { 1.3661 + // end of transmission 1.3662 + if (gbSerialFunction) // external device 1.3663 + gbMemory[0xff01] = gbSerialFunction(gbMemory[0xff01]); 1.3664 + else 1.3665 + gbMemory[0xff01] = 0xff; 1.3666 + gbSerialTicks = 0; 1.3667 + gbMemory[0xff02] &= 0x7f; 1.3668 + gbSerialOn = 0; 1.3669 + gbInterrupt |= 8; 1.3670 + gbSerialBits = 0; 1.3671 + } 1.3672 + else 1.3673 + gbSerialTicks += GBSERIAL_CLOCK_TICKS; 1.3674 + } 1.3675 + } 1.3676 +#ifdef LINK_EMULATION 1.3677 + } 1.3678 +#endif 1.3679 + } 1.3680 + 1.3681 + // timer emulation 1.3682 + if (gbTimerOn) 1.3683 + { 1.3684 + gbTimerTicks -= clockTicks; 1.3685 + 1.3686 + while (gbTimerTicks <= 0) 1.3687 + { 1.3688 + register_TIMA++; 1.3689 + 1.3690 + if (register_TIMA == 0) 1.3691 + { 1.3692 + // timer overflow! 1.3693 + 1.3694 + // reload timer modulo 1.3695 + register_TIMA = register_TMA; 1.3696 + 1.3697 + // flag interrupt 1.3698 + gbInterrupt |= 4; 1.3699 + } 1.3700 + 1.3701 + gbTimerTicks += gbTimerClockTicks; 1.3702 + } 1.3703 + } 1.3704 + 1.3705 + /* 1.3706 + if(soundOffFlag) 1.3707 + { 1.3708 + if(synchronize && !speedup) 1.3709 + { 1.3710 + synchronizeTicks -= clockTicks; 1.3711 + 1.3712 + while(synchronizeTicks < 0) 1.3713 + { 1.3714 + synchronizeTicks += SYNCHRONIZE_CLOCK_TICKS; 1.3715 + 1.3716 + DWORD now = timeGetTime(); 1.3717 + gbElapsedTime += (now - timeNow); 1.3718 + 1.3719 + if(gbElapsedTime < 50) 1.3720 + { 1.3721 + DWORD diff = 50 - gbElapsedTime; 1.3722 + Sleep(diff); 1.3723 + timeNow = timeGetTime(); 1.3724 + elapsedTime = timeNow - now - diff; 1.3725 + if((int)elapsedTime < 0) 1.3726 + elapsedTime = 0; 1.3727 + } else 1.3728 + { 1.3729 + timeNow = timeGetTime(); 1.3730 + elapsedTime = 0; 1.3731 + } 1.3732 + } 1.3733 + } 1.3734 + } 1.3735 + */ 1.3736 + 1.3737 + soundTicks -= clockTicks; 1.3738 + while (soundTicks < 0) // must be < 1 when soundtick_t is real data type 1.3739 + { 1.3740 + soundTicks += SOUND_CLOCK_TICKS; 1.3741 + 1.3742 + gbSoundTick(); 1.3743 + } 1.3744 + 1.3745 + register_IF = gbInterrupt; 1.3746 + 1.3747 + if (IFF & 0x20) 1.3748 + { 1.3749 + IFF &= 0xdf; 1.3750 + IFF |= 0x01; 1.3751 + gbInterruptWait = 0; 1.3752 + } 1.3753 + else if (gbInterrupt) 1.3754 + { 1.3755 + if (gbInterruptWait == 0) 1.3756 + { 1.3757 + // gbInterruptWait = 0; 1.3758 + 1.3759 + if (IFF & 0x01) 1.3760 + { 1.3761 + if ((gbInterrupt & 1) && (register_IE & 1)) 1.3762 + { 1.3763 + gbVblank_interrupt(); 1.3764 + continue; 1.3765 + } 1.3766 + 1.3767 + if ((gbInterrupt & 2) && (register_IE & 2)) 1.3768 + { 1.3769 + gbLcd_interrupt(); 1.3770 + continue; 1.3771 + } 1.3772 + 1.3773 + if ((gbInterrupt & 4) && (register_IE & 4)) 1.3774 + { 1.3775 + gbTimer_interrupt(); 1.3776 + continue; 1.3777 + } 1.3778 + 1.3779 + if ((gbInterrupt & 8) && (register_IE & 8)) 1.3780 + { 1.3781 + gbSerial_interrupt(); 1.3782 + continue; 1.3783 + } 1.3784 + 1.3785 + if ((gbInterrupt & 16) && (register_IE & 16)) 1.3786 + { 1.3787 + gbJoypad_interrupt(); 1.3788 + continue; 1.3789 + } 1.3790 + } 1.3791 + } 1.3792 + else 1.3793 + { 1.3794 + gbInterruptWait -= clockTicks; 1.3795 + if (gbInterruptWait < 0) 1.3796 + gbInterruptWait = 0; 1.3797 + } 1.3798 + } 1.3799 + 1.3800 + if (useOldFrameTiming) 1.3801 + { 1.3802 + // old timing code 1.3803 + if (ticksToStop > 0) 1.3804 + continue; 1.3805 + } 1.3806 + else 1.3807 + { 1.3808 + if (!newFrame && (register_LCDC & 0x80) != 0) 1.3809 + continue; 1.3810 + } 1.3811 + 1.3812 + if (!(register_LCDC & 0x80)) 1.3813 + { 1.3814 + if (!useOldFrameTiming) 1.3815 + { 1.3816 + // FIXME: since register_LY can be reset to 0 by some games, frame length is variable 1.3817 + // and infinite loops can occurr 1.3818 + // for now, it IS necessary to do something on this condition or games like 1.3819 + // Megaman would freeze upon low-level restart interrupt sequence (Start+Select+A+B). 1.3820 + // the only sensible way to fix this issue is to implement the RIGHT frame timing 1.3821 +#ifdef WANTS_INCOMPLETE_WORKAROUND 1.3822 + if (systemReadJoypads()) 1.3823 + { 1.3824 + if (gbSgbMode && gbSgbMultiplayer) 1.3825 + { 1.3826 + if (gbSgbFourPlayers) 1.3827 + { 1.3828 + gbJoymask[0] = systemGetJoypad(0, false); 1.3829 + gbJoymask[1] = systemGetJoypad(1, false); 1.3830 + gbJoymask[2] = systemGetJoypad(2, false); 1.3831 + gbJoymask[3] = systemGetJoypad(3, false); 1.3832 + } 1.3833 + else 1.3834 + { 1.3835 + gbJoymask[0] = systemGetJoypad(0, false); 1.3836 + gbJoymask[1] = systemGetJoypad(1, false); 1.3837 + } 1.3838 + } 1.3839 + else 1.3840 + { 1.3841 + gbJoymask[0] = systemGetJoypad(0, false); 1.3842 + } 1.3843 + } 1.3844 + else 1.3845 + gbJoymask[0] = gbJoymask[1] = gbJoymask[2] = gbJoymask[3] = 0; 1.3846 +#else 1.3847 +#endif 1.3848 + } 1.3849 + } 1.3850 + 1.3851 + // makes sure frames are really divided across input sampling boundaries which occur at a constant rate 1.3852 + if (newFrame || useOldFrameTiming) 1.3853 + { 1.3854 +/// extern void VBAOnEnteringFrameBoundary(); 1.3855 +/// VBAOnEnteringFrameBoundary(); 1.3856 + 1.3857 + break; 1.3858 + } 1.3859 + } 1.3860 +} 1.3861 + 1.3862 +struct EmulatedSystem GBSystem = 1.3863 +{ 1.3864 + // emuMain 1.3865 + gbEmulate, 1.3866 + // emuReset 1.3867 + gbReset, 1.3868 + // emuCleanUp 1.3869 + gbCleanUp, 1.3870 + // emuReadBattery 1.3871 + gbReadBatteryFile, 1.3872 + // emuWriteBattery 1.3873 + gbWriteBatteryFile, 1.3874 + // emuReadBatteryFromStream 1.3875 + gbReadBatteryFromStream, 1.3876 + // emuWriteBatteryToStream 1.3877 + gbWriteBatteryToStream, 1.3878 + // emuReadState 1.3879 + gbReadSaveState, 1.3880 + // emuWriteState 1.3881 + gbWriteSaveState, 1.3882 + // emuReadStateFromStream 1.3883 + gbReadSaveStateFromStream, 1.3884 + // emuWriteStateToStream 1.3885 + gbWriteSaveStateToStream, 1.3886 + // emuReadMemState 1.3887 + gbReadMemSaveState, 1.3888 + // emuWriteMemState 1.3889 + gbWriteMemSaveState, 1.3890 + // emuWritePNG 1.3891 + gbWritePNGFile, 1.3892 + // emuWriteBMP 1.3893 + gbWriteBMPFile, 1.3894 + // emuUpdateCPSR 1.3895 + NULL, 1.3896 + // emuHasDebugger 1.3897 + false, 1.3898 + // emuCount 1.3899 +#ifdef FINAL_VERSION 1.3900 + 70000 / 4, 1.3901 +#else 1.3902 + 1000, 1.3903 +#endif 1.3904 +}; 1.3905 + 1.3906 +// is there a reason to use more than one set of counters? 1.3907 +EmulatedSystemCounters &GBSystemCounters = systemCounters; 1.3908 + 1.3909 +/* 1.3910 + EmulatedSystemCounters GBSystemCounters = 1.3911 + { 1.3912 + // frameCount 1.3913 + 0, 1.3914 + // lagCount 1.3915 + 0, 1.3916 + // lagged 1.3917 + true, 1.3918 + // laggedLast 1.3919 + true, 1.3920 + }; 1.3921 + */
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/src/gb/GB.h Sat Mar 03 11:44:47 2012 -0600 2.3 @@ -0,0 +1,50 @@ 2.4 +#ifndef VBA_GB_H 2.5 +#define VBA_GB_H 2.6 + 2.7 +#if _MSC_VER > 1000 2.8 +#pragma once 2.9 +#endif // _MSC_VER > 1000 2.10 + 2.11 +#include "zlib.h" 2.12 +#include "../Port.h" 2.13 + 2.14 +typedef union 2.15 +{ 2.16 + struct 2.17 + { 2.18 +#ifdef WORDS_BIGENDIAN 2.19 + u8 B1, B0; 2.20 +#else 2.21 + u8 B0, B1; 2.22 +#endif 2.23 + } B; 2.24 + u16 W; 2.25 +} gbRegister; 2.26 + 2.27 +extern bool gbLoadRom(const char *); 2.28 +extern void gbEmulate(int); 2.29 +extern bool gbIsGameboyRom(const char *); 2.30 +extern void gbSoundReset(); 2.31 +extern void gbSoundSetQuality(int); 2.32 +extern void gbReset(bool userReset = false); 2.33 +extern void gbCleanUp(); 2.34 +extern bool gbWriteBatteryFile(const char *); 2.35 +extern bool gbWriteBatteryFile(const char *, bool); 2.36 +extern bool gbWriteBatteryToStream(gzFile); 2.37 +extern bool gbReadBatteryFile(const char *); 2.38 +extern bool gbReadBatteryFromStream(gzFile); 2.39 +extern bool gbWriteSaveState(const char *); 2.40 +extern bool gbWriteMemSaveState(char *, int); 2.41 +extern bool gbReadSaveState(const char *); 2.42 +extern bool gbReadMemSaveState(char *, int); 2.43 +extern bool gbReadSaveStateFromStream(gzFile); 2.44 +extern bool gbWriteSaveStateToStream(gzFile); 2.45 +extern void gbSgbRenderBorder(); 2.46 +extern bool gbWritePNGFile(const char *); 2.47 +extern bool gbWriteBMPFile(const char *); 2.48 +extern bool gbReadGSASnapshot(const char *); 2.49 + 2.50 +extern struct EmulatedSystem GBSystem; 2.51 +extern struct EmulatedSystemCounters &GBSystemCounters; 2.52 + 2.53 +#endif // VBA_GB_H
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/src/gb/Makefile.am Sat Mar 03 11:44:47 2012 -0600 3.3 @@ -0,0 +1,21 @@ 3.4 +noinst_LIBRARIES = libgb.a 3.5 + 3.6 +libgb_a_SOURCES = \ 3.7 + gbCheats.cpp \ 3.8 + gbCheats.h \ 3.9 + gbCodesCB.h \ 3.10 + gbCodes.h \ 3.11 + GB.cpp \ 3.12 + GB.h \ 3.13 + gbDis.cpp \ 3.14 + gbGfx.cpp \ 3.15 + gbGlobals.cpp \ 3.16 + gbGlobals.h \ 3.17 + gbMemory.cpp \ 3.18 + gbMemory.h \ 3.19 + gbPrinter.cpp \ 3.20 + gbPrinter.h \ 3.21 + gbSGB.cpp \ 3.22 + gbSGB.h \ 3.23 + gbSound.cpp \ 3.24 + gbSound.h
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/src/gb/gbCheats.cpp Sat Mar 03 11:44:47 2012 -0600 4.3 @@ -0,0 +1,477 @@ 4.4 +#include <cstdio> 4.5 +#include <cstdlib> 4.6 +#include <cctype> 4.7 +#include <cstring> 4.8 + 4.9 +#include "../NLS.h" 4.10 +#include "../common/System.h" 4.11 +#include "../common/Util.h" 4.12 + 4.13 +#include "gbCheats.h" 4.14 +#include "gbGlobals.h" 4.15 + 4.16 +gbCheat gbCheatList[100]; 4.17 +int gbCheatNumber = 0; 4.18 +bool gbCheatMap[0x10000]; 4.19 + 4.20 +extern bool8 cheatsEnabled; 4.21 + 4.22 +#define GBCHEAT_IS_HEX(a) (((a) >= 'A' && (a) <= 'F') || ((a) >= '0' && (a) <= '9')) 4.23 +#define GBCHEAT_HEX_VALUE(a) ((a) >= 'A' ? (a) - 'A' + 10 : (a) - '0') 4.24 + 4.25 +void gbCheatUpdateMap() 4.26 +{ 4.27 + memset(gbCheatMap, 0, 0x10000); 4.28 + 4.29 + for (int i = 0; i < gbCheatNumber; i++) 4.30 + { 4.31 + if (gbCheatList[i].enabled) 4.32 + gbCheatMap[gbCheatList[i].address] = true; 4.33 + } 4.34 +} 4.35 + 4.36 +void gbCheatsSaveGame(gzFile gzFile) 4.37 +{ 4.38 + utilWriteInt(gzFile, gbCheatNumber); 4.39 + if (gbCheatNumber) 4.40 + utilGzWrite(gzFile, &gbCheatList[0], sizeof(gbCheat)*gbCheatNumber); 4.41 +} 4.42 + 4.43 +void gbCheatsReadGame(gzFile gzFile, int version) 4.44 +{ 4.45 + if (version <= 8) 4.46 + { 4.47 + int gbGgOn = utilReadInt(gzFile); 4.48 + 4.49 + if (gbGgOn) 4.50 + { 4.51 + int n = utilReadInt(gzFile); 4.52 + gbXxCheat tmpCheat; 4.53 + for (int i = 0; i < n; i++) 4.54 + { 4.55 + utilGzRead(gzFile, &tmpCheat, sizeof(gbXxCheat)); 4.56 + gbAddGgCheat(tmpCheat.cheatCode, tmpCheat.cheatDesc); 4.57 + } 4.58 + } 4.59 + 4.60 + int gbGsOn = utilReadInt(gzFile); 4.61 + 4.62 + if (gbGsOn) 4.63 + { 4.64 + int n = utilReadInt(gzFile); 4.65 + gbXxCheat tmpCheat; 4.66 + for (int i = 0; i < n; i++) 4.67 + { 4.68 + utilGzRead(gzFile, &tmpCheat, sizeof(gbXxCheat)); 4.69 + gbAddGsCheat(tmpCheat.cheatCode, tmpCheat.cheatDesc); 4.70 + } 4.71 + } 4.72 + } 4.73 + else 4.74 + { 4.75 + gbCheatNumber = utilReadInt(gzFile); 4.76 + 4.77 + if (gbCheatNumber) 4.78 + { 4.79 + utilGzRead(gzFile, &gbCheatList[0], sizeof(gbCheat)*gbCheatNumber); 4.80 + } 4.81 + } 4.82 + 4.83 + gbCheatUpdateMap(); 4.84 +} 4.85 + 4.86 +void gbCheatsSaveCheatList(const char *file) 4.87 +{ 4.88 + if (gbCheatNumber == 0) 4.89 + return; 4.90 + FILE *f = fopen(file, "wb"); 4.91 + if (f == NULL) 4.92 + return; 4.93 + int version = 1; 4.94 + fwrite(&version, 1, sizeof(version), f); 4.95 + int type = 1; 4.96 + fwrite(&type, 1, sizeof(type), f); 4.97 + fwrite(&gbCheatNumber, 1, sizeof(gbCheatNumber), f); 4.98 + fwrite(gbCheatList, 1, sizeof(gbCheatList), f); 4.99 + fclose(f); 4.100 +} 4.101 + 4.102 +bool gbCheatsLoadCheatList(const char *file) 4.103 +{ 4.104 + gbCheatNumber = 0; 4.105 + 4.106 + gbCheatUpdateMap(); 4.107 + 4.108 + int count = 0; 4.109 + 4.110 + FILE *f = fopen(file, "rb"); 4.111 + 4.112 + if (f == NULL) 4.113 + return false; 4.114 + 4.115 + int version = 0; 4.116 + 4.117 + if (fread(&version, 1, sizeof(version), f) != sizeof(version)) 4.118 + { 4.119 + fclose(f); 4.120 + return false; 4.121 + } 4.122 + 4.123 + if (version != 1) 4.124 + { 4.125 + systemMessage(MSG_UNSUPPORTED_CHEAT_LIST_VERSION, 4.126 + N_("Unsupported cheat list version %d"), version); 4.127 + fclose(f); 4.128 + return false; 4.129 + } 4.130 + 4.131 + int type = 0; 4.132 + if (fread(&type, 1, sizeof(type), f) != sizeof(type)) 4.133 + { 4.134 + fclose(f); 4.135 + return false; 4.136 + } 4.137 + 4.138 + if (type != 1) 4.139 + { 4.140 + systemMessage(MSG_UNSUPPORTED_CHEAT_LIST_TYPE, 4.141 + N_("Unsupported cheat list type %d"), type); 4.142 + fclose(f); 4.143 + return false; 4.144 + } 4.145 + 4.146 + if (fread(&count, 1, sizeof(count), f) != sizeof(count)) 4.147 + { 4.148 + fclose(f); 4.149 + return false; 4.150 + } 4.151 + 4.152 + if (fread(gbCheatList, 1, sizeof(gbCheatList), f) != sizeof(gbCheatList)) 4.153 + { 4.154 + fclose(f); 4.155 + return false; 4.156 + } 4.157 + 4.158 + fclose(f); 4.159 + gbCheatNumber = count; 4.160 + gbCheatUpdateMap(); 4.161 + 4.162 + return true; 4.163 +} 4.164 + 4.165 +bool gbVerifyGsCode(const char *code) 4.166 +{ 4.167 + int len = strlen(code); 4.168 + 4.169 + if (len == 0) 4.170 + return true; 4.171 + 4.172 + if (len != 8) 4.173 + return false; 4.174 + 4.175 + for (int i = 0; i < 8; i++) 4.176 + if (!GBCHEAT_IS_HEX(code[i])) 4.177 + return false; 4.178 + 4.179 + int address = GBCHEAT_HEX_VALUE(code[6]) << 12 | 4.180 + GBCHEAT_HEX_VALUE(code[7]) << 8 | 4.181 + GBCHEAT_HEX_VALUE(code[4]) << 4 | 4.182 + GBCHEAT_HEX_VALUE(code[5]); 4.183 + 4.184 + if (address < 0xa000 || 4.185 + address > 0xdfff) 4.186 + return false; 4.187 + 4.188 + return true; 4.189 +} 4.190 + 4.191 +void gbAddGsCheat(const char *code, const char *desc) 4.192 +{ 4.193 + if (gbCheatNumber > 99) 4.194 + { 4.195 + systemMessage(MSG_MAXIMUM_NUMBER_OF_CHEATS, 4.196 + N_("Maximum number of cheats reached.")); 4.197 + return; 4.198 + } 4.199 + 4.200 + if (!gbVerifyGsCode(code)) 4.201 + { 4.202 + systemMessage(MSG_INVALID_GAMESHARK_CODE, 4.203 + N_("Invalid GameShark code: %s"), code); 4.204 + return; 4.205 + } 4.206 + 4.207 + int i = gbCheatNumber; 4.208 + 4.209 + strcpy(gbCheatList[i].cheatCode, code); 4.210 + strcpy(gbCheatList[i].cheatDesc, desc); 4.211 + 4.212 + gbCheatList[i].code = GBCHEAT_HEX_VALUE(code[0]) << 4 | 4.213 + GBCHEAT_HEX_VALUE(code[1]); 4.214 + 4.215 + gbCheatList[i].value = GBCHEAT_HEX_VALUE(code[2]) << 4 | 4.216 + GBCHEAT_HEX_VALUE(code[3]); 4.217 + 4.218 + gbCheatList[i].address = GBCHEAT_HEX_VALUE(code[6]) << 12 | 4.219 + GBCHEAT_HEX_VALUE(code[7]) << 8 | 4.220 + GBCHEAT_HEX_VALUE(code[4]) << 4 | 4.221 + GBCHEAT_HEX_VALUE(code[5]); 4.222 + 4.223 + gbCheatList[i].compare = 0; 4.224 + 4.225 + gbCheatList[i].enabled = true; 4.226 + 4.227 + gbCheatMap[gbCheatList[i].address] = true; 4.228 + 4.229 + gbCheatNumber++; 4.230 +} 4.231 + 4.232 +bool gbVerifyGgCode(const char *code) 4.233 +{ 4.234 + int len = strlen(code); 4.235 + 4.236 + if (len != 11 && 4.237 + len != 7 && 4.238 + len != 6 && 4.239 + len != 0) 4.240 + return false; 4.241 + 4.242 + if (len == 0) 4.243 + return true; 4.244 + 4.245 + if (!GBCHEAT_IS_HEX(code[0])) 4.246 + return false; 4.247 + if (!GBCHEAT_IS_HEX(code[1])) 4.248 + return false; 4.249 + if (!GBCHEAT_IS_HEX(code[2])) 4.250 + return false; 4.251 + if (code[3] != '-') 4.252 + return false; 4.253 + if (!GBCHEAT_IS_HEX(code[4])) 4.254 + return false; 4.255 + if (!GBCHEAT_IS_HEX(code[5])) 4.256 + return false; 4.257 + if (!GBCHEAT_IS_HEX(code[6])) 4.258 + return false; 4.259 + if (code[7] != 0) 4.260 + { 4.261 + if (code[7] != '-') 4.262 + return false; 4.263 + if (code[8] != 0) 4.264 + { 4.265 + if (!GBCHEAT_IS_HEX(code[8])) 4.266 + return false; 4.267 + if (!GBCHEAT_IS_HEX(code[9])) 4.268 + return false; 4.269 + if (!GBCHEAT_IS_HEX(code[10])) 4.270 + return false; 4.271 + } 4.272 + } 4.273 + 4.274 + // int replace = (GBCHEAT_HEX_VALUE(code[0]) << 4) + 4.275 + // GBCHEAT_HEX_VALUE(code[1]); 4.276 + 4.277 + int address = (GBCHEAT_HEX_VALUE(code[2]) << 8) + 4.278 + (GBCHEAT_HEX_VALUE(code[4]) << 4) + 4.279 + (GBCHEAT_HEX_VALUE(code[5])) + 4.280 + ((GBCHEAT_HEX_VALUE(code[6]) ^ 0x0f) << 12); 4.281 + 4.282 + if (address >= 0x8000 && address <= 0x9fff) 4.283 + return false; 4.284 + 4.285 + if (address >= 0xc000) 4.286 + return false; 4.287 + 4.288 + if (code[7] == 0 || code[8] == '0') 4.289 + return true; 4.290 + 4.291 + int compare = (GBCHEAT_HEX_VALUE(code[8]) << 4) + 4.292 + (GBCHEAT_HEX_VALUE(code[10])); 4.293 + compare = compare ^ 0xff; 4.294 + compare = (compare >> 2) | ((compare << 6) & 0xc0); 4.295 + compare ^= 0x45; 4.296 + 4.297 + int cloak = (GBCHEAT_HEX_VALUE(code[8])) ^ (GBCHEAT_HEX_VALUE(code[9])); 4.298 + 4.299 + if (cloak >= 1 && cloak <= 7) 4.300 + return false; 4.301 + 4.302 + return true; 4.303 +} 4.304 + 4.305 +void gbAddGgCheat(const char *code, const char *desc) 4.306 +{ 4.307 + if (gbCheatNumber > 99) 4.308 + { 4.309 + systemMessage(MSG_MAXIMUM_NUMBER_OF_CHEATS, 4.310 + N_("Maximum number of cheats reached.")); 4.311 + return; 4.312 + } 4.313 + 4.314 + if (!gbVerifyGgCode(code)) 4.315 + { 4.316 + systemMessage(MSG_INVALID_GAMEGENIE_CODE, 4.317 + N_("Invalid GameGenie code: %s"), code); 4.318 + return; 4.319 + } 4.320 + 4.321 + int i = gbCheatNumber; 4.322 + 4.323 + int len = strlen(code); 4.324 + 4.325 + strcpy(gbCheatList[i].cheatCode, code); 4.326 + strcpy(gbCheatList[i].cheatDesc, desc); 4.327 + 4.328 + gbCheatList[i].code = 1; 4.329 + gbCheatList[i].value = (GBCHEAT_HEX_VALUE(code[0]) << 4) + 4.330 + GBCHEAT_HEX_VALUE(code[1]); 4.331 + 4.332 + gbCheatList[i].address = (GBCHEAT_HEX_VALUE(code[2]) << 8) + 4.333 + (GBCHEAT_HEX_VALUE(code[4]) << 4) + 4.334 + (GBCHEAT_HEX_VALUE(code[5])) + 4.335 + ((GBCHEAT_HEX_VALUE(code[6]) ^ 0x0f) << 12); 4.336 + 4.337 + gbCheatList[i].compare = 0; 4.338 + 4.339 + if (len != 7 && len != 8) 4.340 + { 4.341 + int compare = (GBCHEAT_HEX_VALUE(code[8]) << 4) + 4.342 + (GBCHEAT_HEX_VALUE(code[10])); 4.343 + compare = compare ^ 0xff; 4.344 + compare = (compare >> 2) | ((compare << 6) & 0xc0); 4.345 + compare ^= 0x45; 4.346 + 4.347 + gbCheatList[i].compare = compare; 4.348 + gbCheatList[i].code = 0; 4.349 + } 4.350 + 4.351 + gbCheatList[i].enabled = true; 4.352 + 4.353 + gbCheatMap[gbCheatList[i].address] = true; 4.354 + 4.355 + gbCheatNumber++; 4.356 +} 4.357 + 4.358 +void gbCheatRemove(int i) 4.359 +{ 4.360 + if (i < 0 || i >= gbCheatNumber) 4.361 + { 4.362 + systemMessage(MSG_INVALID_CHEAT_TO_REMOVE, 4.363 + N_("Invalid cheat to remove %d"), i); 4.364 + return; 4.365 + } 4.366 + 4.367 + if ((i+1) < gbCheatNumber) 4.368 + { 4.369 + memcpy(&gbCheatList[i], &gbCheatList[i+1], sizeof(gbCheat)* 4.370 + (gbCheatNumber-i-1)); 4.371 + } 4.372 + 4.373 + gbCheatNumber--; 4.374 + 4.375 + gbCheatUpdateMap(); 4.376 +} 4.377 + 4.378 +void gbCheatRemoveAll() 4.379 +{ 4.380 + gbCheatNumber = 0; 4.381 + gbCheatUpdateMap(); 4.382 +} 4.383 + 4.384 +void gbCheatEnable(int i) 4.385 +{ 4.386 + if (i >= 0 && i < gbCheatNumber) 4.387 + { 4.388 + if (!gbCheatList[i].enabled) 4.389 + { 4.390 + gbCheatList[i].enabled = true; 4.391 + gbCheatUpdateMap(); 4.392 + } 4.393 + } 4.394 +} 4.395 + 4.396 +void gbCheatDisable(int i) 4.397 +{ 4.398 + if (i >= 0 && i < gbCheatNumber) 4.399 + { 4.400 + if (gbCheatList[i].enabled) 4.401 + { 4.402 + gbCheatList[i].enabled = false; 4.403 + gbCheatUpdateMap(); 4.404 + } 4.405 + } 4.406 +} 4.407 + 4.408 +bool gbCheatReadGSCodeFile(const char *fileName) 4.409 +{ 4.410 + FILE *file = fopen(fileName, "rb"); 4.411 + 4.412 + if (!file) 4.413 + return false; 4.414 + 4.415 + fseek(file, 0x18, SEEK_SET); 4.416 + int count = 0; 4.417 + fread(&count, 1, 2, file); 4.418 + int dummy = 0; 4.419 + gbCheatRemoveAll(); 4.420 + char desc[13]; 4.421 + char code[9]; 4.422 + int i; 4.423 + for (i = 0; i < count; i++) 4.424 + { 4.425 + fread(&dummy, 1, 2, file); 4.426 + fread(desc, 1, 12, file); 4.427 + desc[12] = 0; 4.428 + fread(code, 1, 8, file); 4.429 + code[8] = 0; 4.430 + gbAddGsCheat(code, desc); 4.431 + } 4.432 + 4.433 + for (i = 0; i < gbCheatNumber; i++) 4.434 + gbCheatDisable(i); 4.435 + 4.436 + fclose(file); 4.437 + return true; 4.438 +} 4.439 + 4.440 +u8 gbCheatRead(u16 address) 4.441 +{ 4.442 + if (!cheatsEnabled) 4.443 + return gbReadMemoryQuick(address); 4.444 + 4.445 + for (int i = 0; i < gbCheatNumber; i++) 4.446 + { 4.447 + if (gbCheatList[i].enabled && gbCheatList[i].address == address) 4.448 + { 4.449 + switch (gbCheatList[i].code) 4.450 + { 4.451 + case 0x100: // GameGenie support 4.452 + if (gbReadMemoryQuick(address) == gbCheatList[i].compare) 4.453 + return gbCheatList[i].value; 4.454 + break; 4.455 + case 0x00: 4.456 + case 0x01: 4.457 + case 0x80: 4.458 + return gbCheatList[i].value; 4.459 + case 0x90: 4.460 + case 0x91: 4.461 + case 0x92: 4.462 + case 0x93: 4.463 + case 0x94: 4.464 + case 0x95: 4.465 + case 0x96: 4.466 + case 0x97: 4.467 + if (address >= 0xd000 && address < 0xe000) 4.468 + { 4.469 + if (((gbMemoryMap[0x0d] - gbWram)/0x1000) == 4.470 + (gbCheatList[i].code - 0x90)) 4.471 + return gbCheatList[i].value; 4.472 + } 4.473 + else 4.474 + return gbCheatList[i].value; 4.475 + } 4.476 + } 4.477 + } 4.478 + return gbReadMemoryQuick(address); 4.479 +} 4.480 +
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/src/gb/gbCheats.h Sat Mar 03 11:44:47 2012 -0600 5.3 @@ -0,0 +1,44 @@ 5.4 +#ifndef VBA_GB_CHEATS_H 5.5 +#define VBA_GB_CHEATS_H 5.6 + 5.7 +#if _MSC_VER > 1000 5.8 +#pragma once 5.9 +#endif // _MSC_VER > 1000 5.10 + 5.11 +struct gbXxCheat 5.12 +{ 5.13 + char cheatDesc[100]; 5.14 + char cheatCode[20]; 5.15 +}; 5.16 + 5.17 +struct gbCheat 5.18 +{ 5.19 + char cheatCode[20]; 5.20 + char cheatDesc[32]; 5.21 + u16 address; 5.22 + int code; 5.23 + u8 compare; 5.24 + u8 value; 5.25 + bool enabled; 5.26 +}; 5.27 + 5.28 +extern void gbCheatsSaveGame(gzFile); 5.29 +extern void gbCheatsReadGame(gzFile, int); 5.30 +extern void gbCheatsSaveCheatList(const char *); 5.31 +extern bool gbCheatsLoadCheatList(const char *); 5.32 +extern bool gbCheatReadGSCodeFile(const char *); 5.33 + 5.34 +extern void gbAddGsCheat(const char *, const char *); 5.35 +extern void gbAddGgCheat(const char *, const char *); 5.36 +extern void gbCheatRemove(int); 5.37 +extern void gbCheatRemoveAll(); 5.38 +extern void gbCheatEnable(int); 5.39 +extern void gbCheatDisable(int); 5.40 +extern u8 gbCheatRead(u16); 5.41 + 5.42 +extern int gbCheatNumber; 5.43 +extern gbCheat gbCheatList[100]; 5.44 +extern bool gbCheatMap[0x10000]; 5.45 + 5.46 +#endif // VBA_GB_CHEATS_H 5.47 +
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/src/gb/gbCodes.h Sat Mar 03 11:44:47 2012 -0600 6.3 @@ -0,0 +1,1388 @@ 6.4 + case 0x00: 6.5 + // NOP 6.6 + break; 6.7 + case 0x01: 6.8 + // LD BC, NNNN 6.9 + BC.B.B0=gbReadMemory(PC.W++); 6.10 + BC.B.B1=gbReadMemory(PC.W++); 6.11 + break; 6.12 + case 0x02: 6.13 + // LD (BC),A 6.14 + gbWriteMemory(BC.W,AF.B.B1); 6.15 + break; 6.16 + case 0x03: 6.17 + // INC BC 6.18 + BC.W++; 6.19 + break; 6.20 + case 0x04: 6.21 + // INC B 6.22 + BC.B.B1++; 6.23 + AF.B.B0= (AF.B.B0 & C_FLAG)|ZeroTable[BC.B.B1]| (BC.B.B1&0x0F? 0:H_FLAG); 6.24 + break; 6.25 + case 0x05: 6.26 + // DEC B 6.27 + BC.B.B1--; 6.28 + AF.B.B0= N_FLAG|(AF.B.B0 & C_FLAG)|ZeroTable[BC.B.B1]| 6.29 + ((BC.B.B1&0x0F)==0x0F? H_FLAG:0); 6.30 + break; 6.31 + case 0x06: 6.32 + // LD B, NN 6.33 + BC.B.B1=gbReadOpcode(PC.W++); 6.34 + break; 6.35 + case 0x07: 6.36 + // RLCA 6.37 + tempValue=AF.B.B1&0x80? C_FLAG:0; 6.38 + AF.B.B1=((AF.B.B1<<1)|(AF.B.B1>>7)) & 0xFF; 6.39 + AF.B.B0=tempValue; 6.40 + break; 6.41 + case 0x08: 6.42 + // LD (NNNN), SP 6.43 + tempRegister.B.B0=gbReadOpcode(PC.W++); 6.44 + tempRegister.B.B1=gbReadOpcode(PC.W++); 6.45 + gbWriteMemory(tempRegister.W++,SP.B.B0); 6.46 + gbWriteMemory(tempRegister.W,SP.B.B1); 6.47 + break; 6.48 + case 0x09: 6.49 + // ADD HL,BC 6.50 + tempRegister.W=(HL.W+BC.W)&0xFFFF; 6.51 + AF.B.B0= (AF.B.B0 & Z_FLAG)| ((HL.W^BC.W^tempRegister.W)&0x1000? H_FLAG:0)| 6.52 + (((long)HL.W+(long)BC.W)&0x10000? C_FLAG:0); 6.53 + HL.W=tempRegister.W; 6.54 + break; 6.55 + case 0x0a: 6.56 + // LD A,(BC) 6.57 + AF.B.B1=gbReadMemory(BC.W); 6.58 + break; 6.59 + case 0x0b: 6.60 + // DEC BC 6.61 + BC.W--; 6.62 + break; 6.63 + case 0x0c: 6.64 + // INC C 6.65 + BC.B.B0++; 6.66 + AF.B.B0= (AF.B.B0 & C_FLAG)|ZeroTable[BC.B.B0]| (BC.B.B0&0x0F? 0:H_FLAG); 6.67 + break; 6.68 + case 0x0d: 6.69 + // DEC C 6.70 + BC.B.B0--; 6.71 + AF.B.B0= N_FLAG|(AF.B.B0 & C_FLAG)|ZeroTable[BC.B.B0]| 6.72 + ((BC.B.B0&0x0F)==0x0F? H_FLAG:0); 6.73 + break; 6.74 + case 0x0e: 6.75 + // LD C, NN 6.76 + BC.B.B0=gbReadOpcode(PC.W++); 6.77 + break; 6.78 + case 0x0f: 6.79 + // RRCA 6.80 + tempValue=AF.B.B1&0x01; 6.81 + AF.B.B1=(AF.B.B1>>1)|(tempValue? 0x80:0); 6.82 + AF.B.B0=(tempValue<<4); 6.83 + break; 6.84 + case 0x10: 6.85 + // STOP 6.86 + opcode = gbReadOpcode(PC.W++); 6.87 + if(gbCgbMode) { 6.88 + if(gbReadMemoryQuick(0xff4d) & 1) { 6.89 + gbSpeedSwitch(); 6.90 + 6.91 + if(gbSpeed == 0) 6.92 + gbWriteMemoryQuick(0xff4d, 0x00); 6.93 + else 6.94 + gbWriteMemoryQuick(0xff4d, 0x80); 6.95 + } 6.96 + } 6.97 + break; 6.98 + case 0x11: 6.99 + // LD DE, NNNN 6.100 + DE.B.B0=gbReadMemory(PC.W++); 6.101 + DE.B.B1=gbReadMemory(PC.W++); 6.102 + break; 6.103 + case 0x12: 6.104 + // LD (DE),A 6.105 + gbWriteMemory(DE.W,AF.B.B1); 6.106 + break; 6.107 + case 0x13: 6.108 + // INC DE 6.109 + DE.W++; 6.110 + break; 6.111 + case 0x14: 6.112 + // INC D 6.113 + DE.B.B1++; 6.114 + AF.B.B0= (AF.B.B0 & C_FLAG)|ZeroTable[DE.B.B1]| (DE.B.B1&0x0F? 0:H_FLAG); 6.115 + break; 6.116 + case 0x15: 6.117 + // DEC D 6.118 + DE.B.B1--; 6.119 + AF.B.B0= N_FLAG|(AF.B.B0 & C_FLAG)|ZeroTable[DE.B.B1]| 6.120 + ((DE.B.B1&0x0F)==0x0F? H_FLAG:0); 6.121 + break; 6.122 + case 0x16: 6.123 + // LD D,NN 6.124 + DE.B.B1=gbReadOpcode(PC.W++); 6.125 + break; 6.126 + case 0x17: 6.127 + // RLA 6.128 + tempValue=AF.B.B1&0x80? C_FLAG:0; 6.129 + AF.B.B1=((AF.B.B1<<1)|((AF.B.B0&C_FLAG)>>4)) & 0xFF; 6.130 + AF.B.B0=tempValue; 6.131 + break; 6.132 + case 0x18: 6.133 + // JR NN 6.134 + PC.W+=(s8)gbReadMemory(PC.W)+1; 6.135 + break; 6.136 + case 0x19: 6.137 + // ADD HL,DE 6.138 + tempRegister.W=(HL.W+DE.W)&0xFFFF; 6.139 + AF.B.B0= (AF.B.B0 & Z_FLAG)| ((HL.W^DE.W^tempRegister.W)&0x1000? H_FLAG:0)| 6.140 + (((long)HL.W+(long)DE.W)&0x10000? C_FLAG:0); 6.141 + HL.W=tempRegister.W; 6.142 + break; 6.143 + case 0x1a: 6.144 + // LD A,(DE) 6.145 + AF.B.B1=gbReadMemory(DE.W); 6.146 + break; 6.147 + case 0x1b: 6.148 + // DEC DE 6.149 + DE.W--; 6.150 + break; 6.151 + case 0x1c: 6.152 + // INC E 6.153 + DE.B.B0++; 6.154 + AF.B.B0= (AF.B.B0 & C_FLAG)|ZeroTable[DE.B.B0]| (DE.B.B0&0x0F? 0:H_FLAG); 6.155 + break; 6.156 + case 0x1d: 6.157 + // DEC E 6.158 + DE.B.B0--; 6.159 + AF.B.B0= N_FLAG|(AF.B.B0 & C_FLAG)|ZeroTable[DE.B.B0]| 6.160 + ((DE.B.B0&0x0F)==0x0F? H_FLAG:0); 6.161 + break; 6.162 + case 0x1e: 6.163 + // LD E,NN 6.164 + DE.B.B0=gbReadOpcode(PC.W++); 6.165 + break; 6.166 + case 0x1f: 6.167 + // RRA 6.168 + tempValue=AF.B.B1&0x01; 6.169 + AF.B.B1=(AF.B.B1>>1)|(AF.B.B0&C_FLAG? 0x80:0); 6.170 + AF.B.B0=(tempValue<<4); 6.171 + break; 6.172 + case 0x20: 6.173 + // JR NZ,NN 6.174 + if(AF.B.B0&Z_FLAG) 6.175 + PC.W++; 6.176 + else { 6.177 + PC.W+=(s8)gbReadMemory(PC.W)+1; 6.178 + clockTicks++; 6.179 + } 6.180 + break; 6.181 + case 0x21: 6.182 + // LD HL,NNNN 6.183 + HL.B.B0=gbReadMemory(PC.W++); 6.184 + HL.B.B1=gbReadMemory(PC.W++); 6.185 + break; 6.186 + case 0x22: 6.187 + // LDI (HL),A 6.188 + gbWriteMemory(HL.W++,AF.B.B1); 6.189 + break; 6.190 + case 0x23: 6.191 + // INC HL 6.192 + HL.W++; 6.193 + break; 6.194 + case 0x24: 6.195 + // INC H 6.196 + HL.B.B1++; 6.197 + AF.B.B0= (AF.B.B0 & C_FLAG)|ZeroTable[HL.B.B1]| (HL.B.B1&0x0F? 0:H_FLAG); 6.198 + break; 6.199 + case 0x25: 6.200 + // DEC H 6.201 + HL.B.B1--; 6.202 + AF.B.B0= N_FLAG|(AF.B.B0 & C_FLAG)|ZeroTable[HL.B.B1]| 6.203 + ((HL.B.B1&0x0F)==0x0F? H_FLAG:0); 6.204 + break; 6.205 + case 0x26: 6.206 + // LD H,NN 6.207 + HL.B.B1=gbReadOpcode(PC.W++); 6.208 + break; 6.209 + case 0x27: 6.210 + // DAA 6.211 + tempRegister.W=AF.B.B1; 6.212 + if(AF.B.B0&C_FLAG) tempRegister.W|=256; 6.213 + if(AF.B.B0&H_FLAG) tempRegister.W|=512; 6.214 + if(AF.B.B0&N_FLAG) tempRegister.W|=1024; 6.215 + AF.W=DAATable[tempRegister.W]; 6.216 + break; 6.217 + case 0x28: 6.218 + // JR Z,NN 6.219 + if(AF.B.B0&Z_FLAG) { 6.220 + PC.W+=(s8)gbReadMemory(PC.W)+1; 6.221 + clockTicks++; 6.222 + } else 6.223 + PC.W++; 6.224 + break; 6.225 + case 0x29: 6.226 + // ADD HL,HL 6.227 + tempRegister.W=(HL.W+HL.W)&0xFFFF; AF.B.B0= (AF.B.B0 & Z_FLAG)| 6.228 + ((HL.W^HL.W^tempRegister.W)&0x1000? H_FLAG:0)| 6.229 + (((long)HL.W+(long)HL.W)&0x10000? C_FLAG:0); 6.230 + HL.W=tempRegister.W; 6.231 + break; 6.232 + case 0x2a: 6.233 + // LDI A,(HL) 6.234 + AF.B.B1 = gbReadMemory(HL.W++); 6.235 + break; 6.236 + case 0x2b: 6.237 + // DEC HL 6.238 + HL.W--; 6.239 + break; 6.240 + case 0x2c: 6.241 + // INC L 6.242 + HL.B.B0++; 6.243 + AF.B.B0= (AF.B.B0 & C_FLAG)|ZeroTable[HL.B.B0]| (HL.B.B0&0x0F? 0:H_FLAG); 6.244 + break; 6.245 + case 0x2d: 6.246 + // DEC L 6.247 + HL.B.B0--; 6.248 + AF.B.B0= N_FLAG|(AF.B.B0 & C_FLAG)|ZeroTable[HL.B.B0]| 6.249 + ((HL.B.B0&0x0F)==0x0F? H_FLAG:0); 6.250 + break; 6.251 + case 0x2e: 6.252 + // LD L,NN 6.253 + HL.B.B0=gbReadOpcode(PC.W++); 6.254 + break; 6.255 + case 0x2f: 6.256 + // CPL 6.257 + AF.B.B1 ^= 255; 6.258 + AF.B.B0|=N_FLAG|H_FLAG; 6.259 + break; 6.260 + case 0x30: 6.261 + // JR NC,NN 6.262 + if(AF.B.B0&C_FLAG) 6.263 + PC.W++; 6.264 + else { 6.265 + PC.W+=(s8)gbReadMemory(PC.W)+1; 6.266 + clockTicks++; 6.267 + } 6.268 + break; 6.269 + case 0x31: 6.270 + // LD SP,NNNN 6.271 + SP.B.B0=gbReadMemory(PC.W++); 6.272 + SP.B.B1=gbReadMemory(PC.W++); 6.273 + break; 6.274 + case 0x32: 6.275 + // LDD (HL),A 6.276 + gbWriteMemory(HL.W--,AF.B.B1); 6.277 + break; 6.278 + case 0x33: 6.279 + // INC SP 6.280 + SP.W++; 6.281 + break; 6.282 + case 0x34: 6.283 + // INC (HL) 6.284 + tempValue=(gbReadMemory(HL.W)+1) & 0xFF; 6.285 + AF.B.B0= (AF.B.B0 & C_FLAG)|ZeroTable[tempValue]| (tempValue&0x0F? 0:H_FLAG); 6.286 + gbWriteMemory(HL.W,tempValue); 6.287 + break; 6.288 + case 0x35: 6.289 + // DEC (HL) 6.290 + tempValue=(gbReadMemory(HL.W)-1) & 0xFF; 6.291 + AF.B.B0= N_FLAG|(AF.B.B0 & C_FLAG)|ZeroTable[tempValue]| 6.292 + ((tempValue&0x0F)==0x0F? H_FLAG:0);gbWriteMemory(HL.W,tempValue); 6.293 + break; 6.294 + case 0x36: 6.295 + // LD (HL),NN 6.296 + gbWriteMemory(HL.W,gbReadOpcode(PC.W++)); 6.297 + break; 6.298 + case 0x37: 6.299 + // SCF 6.300 + AF.B.B0 = AF.B.B0 & Z_FLAG | C_FLAG; 6.301 + break; 6.302 +case 0x38: 6.303 + // JR C,NN 6.304 + if(AF.B.B0&C_FLAG) { 6.305 + PC.W+=(s8)gbReadMemory(PC.W)+1; 6.306 + clockTicks ++; 6.307 + } else 6.308 + PC.W++; 6.309 + break; 6.310 + case 0x39: 6.311 + // ADD HL,SP 6.312 + tempRegister.W=(HL.W+SP.W)&0xFFFF; 6.313 + AF.B.B0= (AF.B.B0 & Z_FLAG)| ((HL.W^SP.W^tempRegister.W)&0x1000? H_FLAG:0)| 6.314 + (((long)HL.W+(long)SP.W)&0x10000? C_FLAG:0); 6.315 + HL.W=tempRegister.W; 6.316 + break; 6.317 + case 0x3a: 6.318 + // LDD A,(HL) 6.319 + AF.B.B1 = gbReadMemory(HL.W--); 6.320 + break; 6.321 + case 0x3b: 6.322 + // DEC SP 6.323 + SP.W--; 6.324 + break; 6.325 + case 0x3c: 6.326 + // INC A 6.327 + AF.B.B1++; 6.328 + AF.B.B0= (AF.B.B0 & C_FLAG)|ZeroTable[AF.B.B1]| (AF.B.B1&0x0F? 0:H_FLAG); 6.329 + break; 6.330 + case 0x3d: 6.331 + // DEC A 6.332 + AF.B.B1--; 6.333 + AF.B.B0= N_FLAG|(AF.B.B0 & C_FLAG)|ZeroTable[AF.B.B1]| 6.334 + ((AF.B.B1&0x0F)==0x0F? H_FLAG:0); 6.335 + break; 6.336 + case 0x3e: 6.337 + // LD A,NN 6.338 + AF.B.B1=gbReadOpcode(PC.W++); 6.339 + break; 6.340 + case 0x3f: 6.341 + // CCF 6.342 + AF.B.B0^=C_FLAG;AF.B.B0&=~(N_FLAG|H_FLAG); 6.343 + break; 6.344 + case 0x40: 6.345 + // LD B,B 6.346 + BC.B.B1=BC.B.B1; 6.347 + break; 6.348 + case 0x41: 6.349 + // LD B,C 6.350 + BC.B.B1=BC.B.B0; 6.351 + break; 6.352 + case 0x42: 6.353 + // LD B,D 6.354 + BC.B.B1=DE.B.B1; 6.355 + break; 6.356 + case 0x43: 6.357 + // LD B,E 6.358 + BC.B.B1=DE.B.B0; 6.359 + break; 6.360 + case 0x44: 6.361 + // LD B,H 6.362 + BC.B.B1=HL.B.B1; 6.363 + break; 6.364 + case 0x45: 6.365 + // LD B,L 6.366 + BC.B.B1=HL.B.B0; 6.367 + break; 6.368 + case 0x46: 6.369 + // LD B,(HL) 6.370 + BC.B.B1=gbReadMemory(HL.W); 6.371 + break; 6.372 + case 0x47: 6.373 + // LD B,A 6.374 + BC.B.B1=AF.B.B1; 6.375 + break; 6.376 + case 0x48: 6.377 + // LD C,B 6.378 + BC.B.B0=BC.B.B1; 6.379 + break; 6.380 + case 0x49: 6.381 + // LD C,C 6.382 + BC.B.B0=BC.B.B0; 6.383 + break; 6.384 + case 0x4a: 6.385 + // LD C,D 6.386 + BC.B.B0=DE.B.B1; 6.387 + break; 6.388 + case 0x4b: 6.389 + // LD C,E 6.390 + BC.B.B0=DE.B.B0; 6.391 + break; 6.392 + case 0x4c: 6.393 + // LD C,H 6.394 + BC.B.B0=HL.B.B1; 6.395 + break; 6.396 + case 0x4d: 6.397 + // LD C,L 6.398 + BC.B.B0=HL.B.B0; 6.399 + break; 6.400 + case 0x4e: 6.401 + // LD C,(HL) 6.402 + BC.B.B0=gbReadMemory(HL.W); 6.403 + break; 6.404 + case 0x4f: 6.405 + // LD C,A 6.406 + BC.B.B0=AF.B.B1; 6.407 + break; 6.408 + case 0x50: 6.409 + // LD D,B 6.410 + DE.B.B1=BC.B.B1; 6.411 + break; 6.412 + case 0x51: 6.413 + // LD D,C 6.414 + DE.B.B1=BC.B.B0; 6.415 + break; 6.416 + case 0x52: 6.417 + // LD D,D 6.418 + DE.B.B1=DE.B.B1; 6.419 + break; 6.420 + case 0x53: 6.421 + // LD D,E 6.422 + DE.B.B1=DE.B.B0; 6.423 + break; 6.424 + case 0x54: 6.425 + // LD D,H 6.426 + DE.B.B1=HL.B.B1; 6.427 + break; 6.428 + case 0x55: 6.429 + // LD D,L 6.430 + DE.B.B1=HL.B.B0; 6.431 + break; 6.432 + case 0x56: 6.433 + // LD D,(HL) 6.434 + DE.B.B1=gbReadMemory(HL.W); 6.435 + break; 6.436 + case 0x57: 6.437 + // LD D,A 6.438 + DE.B.B1=AF.B.B1; 6.439 + break; 6.440 + case 0x58: 6.441 + // LD E,B 6.442 + DE.B.B0=BC.B.B1; 6.443 + break; 6.444 + case 0x59: 6.445 + // LD E,C 6.446 + DE.B.B0=BC.B.B0; 6.447 + break; 6.448 + case 0x5a: 6.449 + // LD E,D 6.450 + DE.B.B0=DE.B.B1; 6.451 + break; 6.452 + case 0x5b: 6.453 + // LD E,E 6.454 + DE.B.B0=DE.B.B0; 6.455 + break; 6.456 + case 0x5c: 6.457 + // LD E,H 6.458 + DE.B.B0=HL.B.B1; 6.459 + break; 6.460 + case 0x5d: 6.461 + // LD E,L 6.462 + DE.B.B0=HL.B.B0; 6.463 + break; 6.464 + case 0x5e: 6.465 + // LD E,(HL) 6.466 + DE.B.B0=gbReadMemory(HL.W); 6.467 + break; 6.468 + case 0x5f: 6.469 + // LD E,A 6.470 + DE.B.B0=AF.B.B1; 6.471 + break; 6.472 + case 0x60: 6.473 + // LD H,B 6.474 + HL.B.B1=BC.B.B1; 6.475 + break; 6.476 + case 0x61: 6.477 + // LD H,C 6.478 + HL.B.B1=BC.B.B0; 6.479 + break; 6.480 + case 0x62: 6.481 + // LD H,D 6.482 + HL.B.B1=DE.B.B1; 6.483 + break; 6.484 + case 0x63: 6.485 + // LD H,E 6.486 + HL.B.B1=DE.B.B0; 6.487 + break; 6.488 + case 0x64: 6.489 + // LD H,H 6.490 + HL.B.B1=HL.B.B1; 6.491 + break; 6.492 + case 0x65: 6.493 + // LD H,L 6.494 + HL.B.B1=HL.B.B0; 6.495 + break; 6.496 + case 0x66: 6.497 + // LD H,(HL) 6.498 + HL.B.B1=gbReadMemory(HL.W); 6.499 + break; 6.500 + case 0x67: 6.501 + // LD H,A 6.502 + HL.B.B1=AF.B.B1; 6.503 + break; 6.504 + case 0x68: 6.505 + // LD L,B 6.506 + HL.B.B0=BC.B.B1; 6.507 + break; 6.508 + case 0x69: 6.509 + // LD L,C 6.510 + HL.B.B0=BC.B.B0; 6.511 + break; 6.512 + case 0x6a: 6.513 + // LD L,D 6.514 + HL.B.B0=DE.B.B1; 6.515 + break; 6.516 + case 0x6b: 6.517 + // LD L,E 6.518 + HL.B.B0=DE.B.B0; 6.519 + break; 6.520 + case 0x6c: 6.521 + // LD L,H 6.522 + HL.B.B0=HL.B.B1; 6.523 + break; 6.524 + case 0x6d: 6.525 + // LD L,L 6.526 + HL.B.B0=HL.B.B0; 6.527 + break; 6.528 + case 0x6e: 6.529 + // LD L,(HL) 6.530 + HL.B.B0=gbReadMemory(HL.W); 6.531 + break; 6.532 + case 0x6f: 6.533 + // LD L,A 6.534 + HL.B.B0=AF.B.B1; 6.535 + break; 6.536 + case 0x70: 6.537 + // LD (HL),B 6.538 + gbWriteMemory(HL.W,BC.B.B1); 6.539 + break; 6.540 + case 0x71: 6.541 + // LD (HL),C 6.542 + gbWriteMemory(HL.W,BC.B.B0); 6.543 + break; 6.544 + case 0x72: 6.545 + // LD (HL),D 6.546 + gbWriteMemory(HL.W,DE.B.B1); 6.547 + break; 6.548 + case 0x73: 6.549 + // LD (HL),E 6.550 + gbWriteMemory(HL.W,DE.B.B0); 6.551 + break; 6.552 + case 0x74: 6.553 + // LD (HL),H 6.554 + gbWriteMemory(HL.W,HL.B.B1); 6.555 + break; 6.556 + case 0x75: 6.557 + // LD (HL),L 6.558 + gbWriteMemory(HL.W,HL.B.B0); 6.559 + break; 6.560 + case 0x76: 6.561 + // HALT 6.562 + if(IFF & 1) { 6.563 + PC.W--; 6.564 + IFF |= 0x80; 6.565 + } else { 6.566 + if((register_IE & register_IF) > 0) 6.567 + IFF |= 0x100; 6.568 + else { 6.569 + PC.W--; 6.570 + IFF |= 0x81; 6.571 + } 6.572 + } 6.573 + break; 6.574 + case 0x77: 6.575 + // LD (HL),A 6.576 + gbWriteMemory(HL.W,AF.B.B1); 6.577 + break; 6.578 + case 0x78: 6.579 + // LD A,B 6.580 + AF.B.B1=BC.B.B1; 6.581 + break; 6.582 + case 0x79: 6.583 + // LD A,C 6.584 + AF.B.B1=BC.B.B0; 6.585 + break; 6.586 + case 0x7a: 6.587 + // LD A,D 6.588 + AF.B.B1=DE.B.B1; 6.589 + break; 6.590 + case 0x7b: 6.591 + // LD A,E 6.592 + AF.B.B1=DE.B.B0; 6.593 + break; 6.594 + case 0x7c: 6.595 + // LD A,H 6.596 + AF.B.B1=HL.B.B1; 6.597 + break; 6.598 + case 0x7d: 6.599 + // LD A,L 6.600 + AF.B.B1=HL.B.B0; 6.601 + break; 6.602 + case 0x7e: 6.603 + // LD A,(HL) 6.604 + AF.B.B1=gbReadMemory(HL.W); 6.605 + break; 6.606 + case 0x7f: 6.607 + // LD A,A 6.608 + AF.B.B1=AF.B.B1; 6.609 + break; 6.610 + case 0x80: 6.611 + // ADD B 6.612 + tempRegister.W=AF.B.B1+BC.B.B1; 6.613 + AF.B.B0= (tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| 6.614 + ((AF.B.B1^BC.B.B1^tempRegister.B.B0)&0x10 ? H_FLAG:0); 6.615 + AF.B.B1=tempRegister.B.B0; 6.616 + break; 6.617 + case 0x81: 6.618 + // ADD C 6.619 + tempRegister.W=AF.B.B1+BC.B.B0; 6.620 + AF.B.B0= (tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| 6.621 + ((AF.B.B1^BC.B.B0^tempRegister.B.B0)&0x10 ? H_FLAG:0); 6.622 + AF.B.B1=tempRegister.B.B0; 6.623 + break; 6.624 + case 0x82: 6.625 + // ADD D 6.626 + tempRegister.W=AF.B.B1+DE.B.B1; 6.627 + AF.B.B0= (tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| 6.628 + ((AF.B.B1^DE.B.B1^tempRegister.B.B0)&0x10 ? H_FLAG:0); 6.629 + AF.B.B1=tempRegister.B.B0; 6.630 + break; 6.631 + case 0x83: 6.632 + // ADD E 6.633 + tempRegister.W=AF.B.B1+DE.B.B0; 6.634 + AF.B.B0= (tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| 6.635 + ((AF.B.B1^DE.B.B0^tempRegister.B.B0)&0x10 ? H_FLAG:0); 6.636 + AF.B.B1=tempRegister.B.B0; 6.637 + break; 6.638 + case 0x84: 6.639 + // ADD H 6.640 + tempRegister.W=AF.B.B1+HL.B.B1; 6.641 + AF.B.B0= (tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| 6.642 + ((AF.B.B1^HL.B.B1^tempRegister.B.B0)&0x10 ? H_FLAG:0); 6.643 + AF.B.B1=tempRegister.B.B0; 6.644 + break; 6.645 + case 0x85: 6.646 + // ADD L 6.647 + tempRegister.W=AF.B.B1+HL.B.B0; 6.648 + AF.B.B0= (tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| 6.649 + ((AF.B.B1^HL.B.B0^tempRegister.B.B0)&0x10 ? H_FLAG:0); 6.650 + AF.B.B1=tempRegister.B.B0; 6.651 + break; 6.652 + case 0x86: 6.653 + // ADD (HL) 6.654 + tempValue=gbReadMemory(HL.W); 6.655 + tempRegister.W=AF.B.B1+tempValue; 6.656 + AF.B.B0= (tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| 6.657 + ((AF.B.B1^tempValue^tempRegister.B.B0)&0x10 ? H_FLAG:0); 6.658 + AF.B.B1=tempRegister.B.B0; 6.659 + break; 6.660 + case 0x87: 6.661 + // ADD A 6.662 + tempRegister.W=AF.B.B1+AF.B.B1; 6.663 + AF.B.B0= (tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| 6.664 + ((AF.B.B1^AF.B.B1^tempRegister.B.B0)&0x10 ? H_FLAG:0); 6.665 + AF.B.B1=tempRegister.B.B0; 6.666 + break; 6.667 + case 0x88: 6.668 + // ADC B: 6.669 + tempRegister.W=AF.B.B1+BC.B.B1+(AF.B.B0&C_FLAG ? 1 : 0); 6.670 + AF.B.B0= (tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| 6.671 + ((AF.B.B1^BC.B.B1^tempRegister.B.B0)&0x10?H_FLAG:0); 6.672 + AF.B.B1=tempRegister.B.B0; 6.673 + break; 6.674 + case 0x89: 6.675 + // ADC C 6.676 + tempRegister.W=AF.B.B1+BC.B.B0+(AF.B.B0&C_FLAG ? 1 : 0); 6.677 + AF.B.B0= (tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| 6.678 + ((AF.B.B1^BC.B.B0^tempRegister.B.B0)&0x10?H_FLAG:0); 6.679 + AF.B.B1=tempRegister.B.B0; 6.680 + break; 6.681 + case 0x8a: 6.682 + // ADC D 6.683 + tempRegister.W=AF.B.B1+DE.B.B1+(AF.B.B0&C_FLAG ? 1 : 0); 6.684 + AF.B.B0= (tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| 6.685 + ((AF.B.B1^DE.B.B1^tempRegister.B.B0)&0x10?H_FLAG:0); 6.686 + AF.B.B1=tempRegister.B.B0; 6.687 + break; 6.688 + case 0x8b: 6.689 + // ADC E 6.690 + tempRegister.W=AF.B.B1+DE.B.B0+(AF.B.B0&C_FLAG ? 1 : 0); 6.691 + AF.B.B0= (tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| 6.692 + ((AF.B.B1^DE.B.B0^tempRegister.B.B0)&0x10?H_FLAG:0); 6.693 + AF.B.B1=tempRegister.B.B0; 6.694 + break; 6.695 + case 0x8c: 6.696 + // ADC H 6.697 + tempRegister.W=AF.B.B1+HL.B.B1+(AF.B.B0&C_FLAG ? 1 : 0); 6.698 + AF.B.B0= (tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| 6.699 + ((AF.B.B1^HL.B.B1^tempRegister.B.B0)&0x10?H_FLAG:0); AF.B.B1=tempRegister.B.B0; 6.700 + break; 6.701 + case 0x8d: 6.702 + // ADC L 6.703 + tempRegister.W=AF.B.B1+HL.B.B0+(AF.B.B0&C_FLAG ? 1 : 0); 6.704 + AF.B.B0= (tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| 6.705 + ((AF.B.B1^HL.B.B0^tempRegister.B.B0)&0x10?H_FLAG:0); 6.706 + AF.B.B1=tempRegister.B.B0; 6.707 + break; 6.708 + case 0x8e: 6.709 + // ADC (HL) 6.710 + tempValue=gbReadMemory(HL.W); 6.711 + tempRegister.W=AF.B.B1+tempValue+(AF.B.B0&C_FLAG ? 1 : 0); 6.712 + AF.B.B0= (tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| 6.713 + ((AF.B.B1^tempValue^tempRegister.B.B0)&0x10?H_FLAG:0); 6.714 + AF.B.B1=tempRegister.B.B0; 6.715 + break; 6.716 + case 0x8f: 6.717 + // ADC A 6.718 + tempRegister.W=AF.B.B1+AF.B.B1+(AF.B.B0&C_FLAG ? 1 : 0); 6.719 + AF.B.B0= (tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| 6.720 + ((AF.B.B1^AF.B.B1^tempRegister.B.B0)&0x10?H_FLAG:0); 6.721 + AF.B.B1=tempRegister.B.B0; 6.722 + break; 6.723 + case 0x90: 6.724 + // SUB B 6.725 + tempRegister.W=AF.B.B1-BC.B.B1; 6.726 + AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| 6.727 + ((AF.B.B1^BC.B.B1^tempRegister.B.B0)&0x10?H_FLAG:0); 6.728 + AF.B.B1=tempRegister.B.B0; 6.729 + break; 6.730 + case 0x91: 6.731 + // SUB C 6.732 + tempRegister.W=AF.B.B1-BC.B.B0; 6.733 + AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| 6.734 + ((AF.B.B1^BC.B.B0^tempRegister.B.B0)&0x10?H_FLAG:0); 6.735 + AF.B.B1=tempRegister.B.B0; 6.736 + break; 6.737 + case 0x92: 6.738 + // SUB D 6.739 + tempRegister.W=AF.B.B1-DE.B.B1; 6.740 + AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| 6.741 + ((AF.B.B1^DE.B.B1^tempRegister.B.B0)&0x10?H_FLAG:0); 6.742 + AF.B.B1=tempRegister.B.B0; 6.743 + break; 6.744 + case 0x93: 6.745 + // SUB E 6.746 + tempRegister.W=AF.B.B1-DE.B.B0; 6.747 + AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| 6.748 + ((AF.B.B1^DE.B.B0^tempRegister.B.B0)&0x10?H_FLAG:0); 6.749 + AF.B.B1=tempRegister.B.B0; 6.750 + break; 6.751 + case 0x94: 6.752 + // SUB H 6.753 + tempRegister.W=AF.B.B1-HL.B.B1; 6.754 + AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| 6.755 + ((AF.B.B1^HL.B.B1^tempRegister.B.B0)&0x10?H_FLAG:0); 6.756 + AF.B.B1=tempRegister.B.B0; 6.757 + break; 6.758 + case 0x95: 6.759 + // SUB L 6.760 + tempRegister.W=AF.B.B1-HL.B.B0; 6.761 + AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| 6.762 + ((AF.B.B1^HL.B.B0^tempRegister.B.B0)&0x10?H_FLAG:0); 6.763 + AF.B.B1=tempRegister.B.B0; 6.764 + break; 6.765 + case 0x96: 6.766 + // SUB (HL) 6.767 + tempValue=gbReadMemory(HL.W); 6.768 + tempRegister.W=AF.B.B1-tempValue; 6.769 + AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| 6.770 + ((AF.B.B1^tempValue^tempRegister.B.B0)&0x10?H_FLAG:0); 6.771 + AF.B.B1=tempRegister.B.B0; 6.772 + break; 6.773 + case 0x97: 6.774 + // SUB A 6.775 + AF.B.B1=0; 6.776 + AF.B.B0=N_FLAG|Z_FLAG; 6.777 + break; 6.778 + case 0x98: 6.779 + // SBC B 6.780 + tempRegister.W=AF.B.B1-BC.B.B1-(AF.B.B0&C_FLAG ? 1 : 0); 6.781 + AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| 6.782 + ((AF.B.B1^BC.B.B1^tempRegister.B.B0)&0x10?H_FLAG:0); 6.783 + AF.B.B1=tempRegister.B.B0; 6.784 + break; 6.785 + case 0x99: 6.786 + // SBC C 6.787 + tempRegister.W=AF.B.B1-BC.B.B0-(AF.B.B0&C_FLAG ? 1 : 0); 6.788 + AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| 6.789 + ((AF.B.B1^BC.B.B0^tempRegister.B.B0)&0x10?H_FLAG:0); 6.790 + AF.B.B1=tempRegister.B.B0; 6.791 + break; 6.792 + case 0x9a: 6.793 + // SBC D 6.794 + tempRegister.W=AF.B.B1-DE.B.B1-(AF.B.B0&C_FLAG ? 1 : 0); 6.795 + AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| 6.796 + ((AF.B.B1^DE.B.B1^tempRegister.B.B0)&0x10?H_FLAG:0); 6.797 + AF.B.B1=tempRegister.B.B0; 6.798 + break; 6.799 + case 0x9b: 6.800 + // SBC E 6.801 + tempRegister.W=AF.B.B1-DE.B.B0-(AF.B.B0&C_FLAG ? 1 : 0); 6.802 + AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| 6.803 + ((AF.B.B1^DE.B.B0^tempRegister.B.B0)&0x10?H_FLAG:0); 6.804 + AF.B.B1=tempRegister.B.B0; 6.805 + break; 6.806 + case 0x9c: 6.807 + // SBC H 6.808 + tempRegister.W=AF.B.B1-HL.B.B1-(AF.B.B0&C_FLAG ? 1 : 0); 6.809 + AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| 6.810 + ((AF.B.B1^HL.B.B1^tempRegister.B.B0)&0x10?H_FLAG:0); 6.811 + AF.B.B1=tempRegister.B.B0; 6.812 + break; 6.813 + case 0x9d: 6.814 + // SBC L 6.815 + tempRegister.W=AF.B.B1-HL.B.B0-(AF.B.B0&C_FLAG ? 1 : 0); 6.816 + AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| 6.817 + ((AF.B.B1^HL.B.B0^tempRegister.B.B0)&0x10?H_FLAG:0); 6.818 + AF.B.B1=tempRegister.B.B0; 6.819 + break; 6.820 + case 0x9e: 6.821 + // SBC (HL) 6.822 + tempValue=gbReadMemory(HL.W); 6.823 + tempRegister.W=AF.B.B1-tempValue-(AF.B.B0&C_FLAG ? 1 : 0); 6.824 + AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| 6.825 + ((AF.B.B1^tempValue^tempRegister.B.B0)&0x10?H_FLAG:0); 6.826 + AF.B.B1=tempRegister.B.B0; 6.827 + break; 6.828 + case 0x9f: 6.829 + // SBC A 6.830 + tempRegister.W=AF.B.B1-AF.B.B1-(AF.B.B0&C_FLAG ? 1 : 0); 6.831 + AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| 6.832 + ((AF.B.B1^AF.B.B1^tempRegister.B.B0)&0x10?H_FLAG:0); 6.833 + AF.B.B1=tempRegister.B.B0; 6.834 + break; 6.835 + case 0xa0: 6.836 + // AND B 6.837 + AF.B.B1&=BC.B.B1; 6.838 + AF.B.B0=H_FLAG|ZeroTable[AF.B.B1]; 6.839 + break; 6.840 + case 0xa1: 6.841 + // AND C 6.842 + AF.B.B1&=BC.B.B0; 6.843 + AF.B.B0=H_FLAG|ZeroTable[AF.B.B1]; 6.844 + break; 6.845 + case 0xa2: 6.846 + // AND_D 6.847 + AF.B.B1&=DE.B.B1; 6.848 + AF.B.B0=H_FLAG|ZeroTable[AF.B.B1]; 6.849 + break; 6.850 + case 0xa3: 6.851 + // AND E 6.852 + AF.B.B1&=DE.B.B0; 6.853 + AF.B.B0=H_FLAG|ZeroTable[AF.B.B1]; 6.854 + break; 6.855 + case 0xa4: 6.856 + // AND H 6.857 + AF.B.B1&=HL.B.B1; 6.858 + AF.B.B0=H_FLAG|ZeroTable[AF.B.B1]; 6.859 + break; 6.860 + case 0xa5: 6.861 + // AND L 6.862 + AF.B.B1&=HL.B.B0; 6.863 + AF.B.B0=H_FLAG|ZeroTable[AF.B.B1]; 6.864 + break; 6.865 + case 0xa6: 6.866 + // AND (HL) 6.867 + tempValue=gbReadMemory(HL.W); 6.868 + AF.B.B1&=tempValue; 6.869 + AF.B.B0=H_FLAG|ZeroTable[AF.B.B1]; 6.870 + break; 6.871 + case 0xa7: 6.872 + // AND A 6.873 + AF.B.B1&=AF.B.B1; 6.874 + AF.B.B0=H_FLAG|ZeroTable[AF.B.B1]; 6.875 + break; 6.876 + case 0xa8: 6.877 + // XOR B 6.878 + AF.B.B1^=BC.B.B1; 6.879 + AF.B.B0=ZeroTable[AF.B.B1]; 6.880 + break; 6.881 + case 0xa9: 6.882 + // XOR C 6.883 + AF.B.B1^=BC.B.B0; 6.884 + AF.B.B0=ZeroTable[AF.B.B1]; 6.885 + break; 6.886 + case 0xaa: 6.887 + // XOR D 6.888 + AF.B.B1^=DE.B.B1; 6.889 + AF.B.B0=ZeroTable[AF.B.B1]; 6.890 + break; 6.891 + case 0xab: 6.892 + // XOR E 6.893 + AF.B.B1^=DE.B.B0; 6.894 + AF.B.B0=ZeroTable[AF.B.B1]; 6.895 + break; 6.896 + case 0xac: 6.897 + // XOR H 6.898 + AF.B.B1^=HL.B.B1; 6.899 + AF.B.B0=ZeroTable[AF.B.B1]; 6.900 + break; 6.901 + case 0xad: 6.902 + // XOR L 6.903 + AF.B.B1^=HL.B.B0; 6.904 + AF.B.B0=ZeroTable[AF.B.B1]; 6.905 + break; 6.906 + case 0xae: 6.907 + // XOR (HL) 6.908 + tempValue=gbReadMemory(HL.W); 6.909 + AF.B.B1^=tempValue; 6.910 + AF.B.B0=ZeroTable[AF.B.B1]; 6.911 + break; 6.912 + case 0xaf: 6.913 + // XOR A 6.914 + AF.B.B1=0; 6.915 + AF.B.B0=Z_FLAG; 6.916 + break; 6.917 + case 0xb0: 6.918 + // OR B 6.919 + AF.B.B1|=BC.B.B1; 6.920 + AF.B.B0=ZeroTable[AF.B.B1]; 6.921 + break; 6.922 + case 0xb1: 6.923 + // OR C 6.924 + AF.B.B1|=BC.B.B0; 6.925 + AF.B.B0=ZeroTable[AF.B.B1]; 6.926 + break; 6.927 + case 0xb2: 6.928 + // OR D 6.929 + AF.B.B1|=DE.B.B1; 6.930 + AF.B.B0=ZeroTable[AF.B.B1]; 6.931 + break; 6.932 + case 0xb3: 6.933 + // OR E 6.934 + AF.B.B1|=DE.B.B0; 6.935 + AF.B.B0=ZeroTable[AF.B.B1]; 6.936 + break; 6.937 + case 0xb4: 6.938 + // OR H 6.939 + AF.B.B1|=HL.B.B1; 6.940 + AF.B.B0=ZeroTable[AF.B.B1]; 6.941 + break; 6.942 + case 0xb5: 6.943 + // OR L 6.944 + AF.B.B1|=HL.B.B0; 6.945 + AF.B.B0=ZeroTable[AF.B.B1]; 6.946 + break; 6.947 + case 0xb6: 6.948 + // OR (HL) 6.949 + tempValue=gbReadMemory(HL.W); 6.950 + AF.B.B1|=tempValue; 6.951 + AF.B.B0=ZeroTable[AF.B.B1]; 6.952 + break; 6.953 + case 0xb7: 6.954 + // OR A 6.955 + AF.B.B1|=AF.B.B1; 6.956 + AF.B.B0=ZeroTable[AF.B.B1]; 6.957 + break; 6.958 + case 0xb8: 6.959 + // CP B: 6.960 + tempRegister.W=AF.B.B1-BC.B.B1; 6.961 + AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| 6.962 + ((AF.B.B1^BC.B.B1^tempRegister.B.B0)&0x10?H_FLAG:0); 6.963 + break; 6.964 + case 0xb9: 6.965 + // CP C 6.966 + tempRegister.W=AF.B.B1-BC.B.B0; 6.967 + AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| 6.968 + ((AF.B.B1^BC.B.B0^tempRegister.B.B0)&0x10?H_FLAG:0); 6.969 + break; 6.970 + case 0xba: 6.971 + // CP D 6.972 + tempRegister.W=AF.B.B1-DE.B.B1; 6.973 + AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| 6.974 + ((AF.B.B1^DE.B.B1^tempRegister.B.B0)&0x10?H_FLAG:0); 6.975 + break; 6.976 + case 0xbb: 6.977 + // CP E 6.978 + tempRegister.W=AF.B.B1-DE.B.B0; 6.979 + AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| 6.980 + ((AF.B.B1^DE.B.B0^tempRegister.B.B0)&0x10?H_FLAG:0); 6.981 + break; 6.982 + case 0xbc: 6.983 + // CP H 6.984 + tempRegister.W=AF.B.B1-HL.B.B1; 6.985 + AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| 6.986 + ((AF.B.B1^HL.B.B1^tempRegister.B.B0)&0x10?H_FLAG:0); 6.987 + break; 6.988 + case 0xbd: 6.989 + // CP L 6.990 + tempRegister.W=AF.B.B1-HL.B.B0; 6.991 + AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| 6.992 + ((AF.B.B1^HL.B.B0^tempRegister.B.B0)&0x10?H_FLAG:0); 6.993 + break; 6.994 + case 0xbe: 6.995 + // CP (HL) 6.996 + tempValue=gbReadMemory(HL.W); 6.997 + tempRegister.W=AF.B.B1-tempValue; 6.998 + AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| 6.999 + ((AF.B.B1^tempValue^tempRegister.B.B0)&0x10?H_FLAG:0); 6.1000 + break; 6.1001 + case 0xbf: 6.1002 + // CP A 6.1003 + AF.B.B0=N_FLAG|Z_FLAG; 6.1004 + break; 6.1005 + case 0xc0: 6.1006 + // RET NZ 6.1007 + if(!(AF.B.B0&Z_FLAG)) { 6.1008 + PC.B.B0=gbReadMemory(SP.W++); 6.1009 + PC.B.B1=gbReadMemory(SP.W++); 6.1010 + clockTicks += 3; 6.1011 + } 6.1012 + break; 6.1013 + case 0xc1: 6.1014 + // POP BC 6.1015 + BC.B.B0=gbReadMemory(SP.W++); 6.1016 + BC.B.B1=gbReadMemory(SP.W++); 6.1017 + break; 6.1018 + case 0xc2: 6.1019 + // JP NZ,NNNN 6.1020 + if(AF.B.B0&Z_FLAG) 6.1021 + PC.W+=2; 6.1022 + else { 6.1023 + tempRegister.B.B0=gbReadMemory(PC.W++); 6.1024 + tempRegister.B.B1=gbReadMemory(PC.W); 6.1025 + PC.W=tempRegister.W; 6.1026 + clockTicks++; 6.1027 + } 6.1028 + break; 6.1029 + case 0xc3: 6.1030 + // JP NNNN 6.1031 + tempRegister.B.B0=gbReadMemory(PC.W++); 6.1032 + tempRegister.B.B1=gbReadMemory(PC.W); 6.1033 + PC.W=tempRegister.W; 6.1034 + break; 6.1035 + case 0xc4: 6.1036 + // CALL NZ,NNNN 6.1037 + if(AF.B.B0&Z_FLAG) 6.1038 + PC.W+=2; 6.1039 + else { 6.1040 + tempRegister.B.B0=gbReadMemory(PC.W++); 6.1041 + tempRegister.B.B1=gbReadMemory(PC.W++); 6.1042 + gbWriteMemory(--SP.W,PC.B.B1); 6.1043 + gbWriteMemory(--SP.W,PC.B.B0); 6.1044 + PC.W=tempRegister.W; 6.1045 + clockTicks += 3; 6.1046 + } 6.1047 + break; 6.1048 + case 0xc5: 6.1049 + // PUSH BC 6.1050 + gbWriteMemory(--SP.W,BC.B.B1); 6.1051 + gbWriteMemory(--SP.W,BC.B.B0); 6.1052 + break; 6.1053 + case 0xc6: 6.1054 + // ADD NN 6.1055 + tempValue=gbReadOpcode(PC.W++); 6.1056 + tempRegister.W=AF.B.B1+tempValue; 6.1057 + AF.B.B0= (tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| 6.1058 + ((AF.B.B1^tempValue^tempRegister.B.B0)&0x10 ? H_FLAG:0); 6.1059 + AF.B.B1=tempRegister.B.B0; 6.1060 + break; 6.1061 + case 0xc7: 6.1062 + // RST 00 6.1063 + gbWriteMemory(--SP.W,PC.B.B1); 6.1064 + gbWriteMemory(--SP.W,PC.B.B0); 6.1065 + PC.W=0x0000; 6.1066 + break; 6.1067 + case 0xc8: 6.1068 + // RET Z 6.1069 + if(AF.B.B0&Z_FLAG) { 6.1070 + PC.B.B0=gbReadMemory(SP.W++); 6.1071 + PC.B.B1=gbReadMemory(SP.W++); 6.1072 + clockTicks += 3; 6.1073 + } 6.1074 + break; 6.1075 + case 0xc9: 6.1076 + // RET 6.1077 + PC.B.B0=gbReadMemory(SP.W++); 6.1078 + PC.B.B1=gbReadMemory(SP.W++); 6.1079 + break; 6.1080 + case 0xca: 6.1081 + // JP Z,NNNN 6.1082 + if(AF.B.B0&Z_FLAG) { 6.1083 + tempRegister.B.B0=gbReadMemory(PC.W++); 6.1084 + tempRegister.B.B1=gbReadMemory(PC.W); 6.1085 + PC.W=tempRegister.W; 6.1086 + clockTicks++; 6.1087 + } else 6.1088 + PC.W+=2; 6.1089 + break; 6.1090 + // CB done outside 6.1091 + case 0xcc: 6.1092 + // CALL Z,NNNN 6.1093 + if(AF.B.B0&Z_FLAG) { 6.1094 + tempRegister.B.B0=gbReadMemory(PC.W++); 6.1095 + tempRegister.B.B1=gbReadMemory(PC.W++); 6.1096 + gbWriteMemory(--SP.W,PC.B.B1); 6.1097 + gbWriteMemory(--SP.W,PC.B.B0); 6.1098 + PC.W=tempRegister.W; 6.1099 + clockTicks += 3; 6.1100 + } else 6.1101 + PC.W+=2; 6.1102 + break; 6.1103 + case 0xcd: 6.1104 + // CALL NNNN 6.1105 + tempRegister.B.B0=gbReadMemory(PC.W++); 6.1106 + tempRegister.B.B1=gbReadMemory(PC.W++); 6.1107 + gbWriteMemory(--SP.W,PC.B.B1); 6.1108 + gbWriteMemory(--SP.W,PC.B.B0); 6.1109 + PC.W=tempRegister.W; 6.1110 + break; 6.1111 + case 0xce: 6.1112 + // ADC NN 6.1113 + tempValue=gbReadOpcode(PC.W++); 6.1114 + tempRegister.W=AF.B.B1+tempValue+(AF.B.B0&C_FLAG ? 1 : 0); 6.1115 + AF.B.B0= (tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| 6.1116 + ((AF.B.B1^tempValue^tempRegister.B.B0)&0x10?H_FLAG:0); 6.1117 + AF.B.B1=tempRegister.B.B0; 6.1118 + break; 6.1119 + case 0xcf: 6.1120 + // RST 08 6.1121 + gbWriteMemory(--SP.W,PC.B.B1); 6.1122 + gbWriteMemory(--SP.W,PC.B.B0); 6.1123 + PC.W=0x0008; 6.1124 + break; 6.1125 + case 0xd0: 6.1126 + // RET NC 6.1127 + if(!(AF.B.B0&C_FLAG)) { 6.1128 + PC.B.B0=gbReadMemory(SP.W++); 6.1129 + PC.B.B1=gbReadMemory(SP.W++); 6.1130 + clockTicks += 3; 6.1131 + } 6.1132 + break; 6.1133 + case 0xd1: 6.1134 + // POP DE 6.1135 + DE.B.B0=gbReadMemory(SP.W++); 6.1136 + DE.B.B1=gbReadMemory(SP.W++); 6.1137 + break; 6.1138 + case 0xd2: 6.1139 + // JP NC,NNNN 6.1140 + if(AF.B.B0&C_FLAG) 6.1141 + PC.W+=2; 6.1142 + else { 6.1143 + tempRegister.B.B0=gbReadMemory(PC.W++); 6.1144 + tempRegister.B.B1=gbReadMemory(PC.W); 6.1145 + PC.W=tempRegister.W; 6.1146 + clockTicks++; 6.1147 + } 6.1148 + break; 6.1149 + // D3 illegal 6.1150 + case 0xd4: 6.1151 + // CALL NC,NNNN 6.1152 + if(AF.B.B0&C_FLAG) 6.1153 + PC.W+=2; 6.1154 + else { 6.1155 + tempRegister.B.B0=gbReadMemory(PC.W++); 6.1156 + tempRegister.B.B1=gbReadMemory(PC.W++); 6.1157 + gbWriteMemory(--SP.W,PC.B.B1); 6.1158 + gbWriteMemory(--SP.W,PC.B.B0); 6.1159 + PC.W=tempRegister.W; 6.1160 + clockTicks += 3; 6.1161 + } 6.1162 + break; 6.1163 + case 0xd5: 6.1164 + // PUSH DE 6.1165 + gbWriteMemory(--SP.W,DE.B.B1); 6.1166 + gbWriteMemory(--SP.W,DE.B.B0); 6.1167 + break; 6.1168 + case 0xd6: 6.1169 + // SUB NN 6.1170 + tempValue=gbReadOpcode(PC.W++); 6.1171 + tempRegister.W=AF.B.B1-tempValue; 6.1172 + AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| 6.1173 + ((AF.B.B1^tempValue^tempRegister.B.B0)&0x10?H_FLAG:0); 6.1174 + AF.B.B1=tempRegister.B.B0; 6.1175 + break; 6.1176 + case 0xd7: 6.1177 + // RST 10 6.1178 + gbWriteMemory(--SP.W,PC.B.B1); 6.1179 + gbWriteMemory(--SP.W,PC.B.B0); 6.1180 + PC.W=0x0010; 6.1181 + break; 6.1182 + case 0xd8: 6.1183 + // RET C 6.1184 + if(AF.B.B0&C_FLAG) { 6.1185 + PC.B.B0=gbReadMemory(SP.W++); 6.1186 + PC.B.B1=gbReadMemory(SP.W++); 6.1187 + clockTicks += 4; 6.1188 + } 6.1189 + break; 6.1190 + case 0xd9: 6.1191 + // RETI 6.1192 + PC.B.B0=gbReadMemory(SP.W++); 6.1193 + PC.B.B1=gbReadMemory(SP.W++); 6.1194 + IFF |= 0x01; 6.1195 + break; 6.1196 + case 0xda: 6.1197 + // JP C,NNNN 6.1198 + if(AF.B.B0&C_FLAG) { 6.1199 + tempRegister.B.B0=gbReadMemory(PC.W++); 6.1200 + tempRegister.B.B1=gbReadMemory(PC.W); 6.1201 + PC.W=tempRegister.W; 6.1202 + clockTicks++; 6.1203 + } else 6.1204 + PC.W+=2; 6.1205 + break; 6.1206 + // DB illegal 6.1207 + case 0xdc: 6.1208 + // CALL C,NNNN 6.1209 + if(AF.B.B0&C_FLAG) { 6.1210 + tempRegister.B.B0=gbReadMemory(PC.W++); 6.1211 + tempRegister.B.B1=gbReadMemory(PC.W++); 6.1212 + gbWriteMemory(--SP.W,PC.B.B1); 6.1213 + gbWriteMemory(--SP.W,PC.B.B0); 6.1214 + PC.W=tempRegister.W; 6.1215 + clockTicks += 3; 6.1216 + } else 6.1217 + PC.W+=2; 6.1218 + break; 6.1219 + // DD illegal 6.1220 + case 0xde: 6.1221 + // SBC NN 6.1222 + tempValue=gbReadOpcode(PC.W++); 6.1223 + tempRegister.W=AF.B.B1-tempValue-(AF.B.B0&C_FLAG ? 1 : 0); 6.1224 + AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| 6.1225 + ((AF.B.B1^tempValue^tempRegister.B.B0)&0x10?H_FLAG:0); 6.1226 + AF.B.B1=tempRegister.B.B0; 6.1227 + break; 6.1228 + case 0xdf: 6.1229 + // RST 18 6.1230 + gbWriteMemory(--SP.W,PC.B.B1); 6.1231 + gbWriteMemory(--SP.W,PC.B.B0); 6.1232 + PC.W=0x0018; 6.1233 + break; 6.1234 + case 0xe0: 6.1235 + // LD (FF00+NN),A 6.1236 + gbWriteMemory(0xff00 + gbReadOpcode(PC.W++),AF.B.B1); 6.1237 + break; 6.1238 + case 0xe1: 6.1239 + // POP HL 6.1240 + HL.B.B0=gbReadMemory(SP.W++); 6.1241 + HL.B.B1=gbReadMemory(SP.W++); 6.1242 + break; 6.1243 + case 0xe2: 6.1244 + // LD (FF00+C),A 6.1245 + gbWriteMemory(0xff00 + BC.B.B0,AF.B.B1); 6.1246 + break; 6.1247 + // E3 illegal 6.1248 + // E4 illegal 6.1249 + case 0xe5: 6.1250 + // PUSH HL 6.1251 + gbWriteMemory(--SP.W,HL.B.B1); 6.1252 + gbWriteMemory(--SP.W,HL.B.B0); 6.1253 + break; 6.1254 + case 0xe6: 6.1255 + // AND NN 6.1256 + tempValue=gbReadOpcode(PC.W++); 6.1257 + AF.B.B1&=tempValue; 6.1258 + AF.B.B0=H_FLAG|ZeroTable[AF.B.B1]; 6.1259 + break; 6.1260 + case 0xe7: 6.1261 + // RST 20 6.1262 + gbWriteMemory(--SP.W,PC.B.B1); 6.1263 + gbWriteMemory(--SP.W,PC.B.B0); 6.1264 + PC.W=0x0020; 6.1265 + break; 6.1266 + case 0xe8: 6.1267 + // ADD SP,NN 6.1268 + offset = (s8)gbReadOpcode(PC.W++); 6.1269 + 6.1270 + if(offset >= 0) { 6.1271 + tempRegister.W = SP.W + offset; 6.1272 + AF.B.B0 = (SP.W > tempRegister.W ? C_FLAG : 0) | 6.1273 + ((SP.W^offset^tempRegister.W)&0x1000? H_FLAG:0); 6.1274 + SP.W = tempRegister.W; 6.1275 + } else { 6.1276 + tempRegister.W = SP.W + offset; 6.1277 + AF.B.B0 = (SP.W < tempRegister.W ? C_FLAG : 0) | 6.1278 + ((SP.W^offset^tempRegister.W)&0x1000?H_FLAG:0); 6.1279 + SP.W = tempRegister.W; 6.1280 + } 6.1281 + break; 6.1282 + case 0xe9: 6.1283 + // LD PC,HL 6.1284 + PC.W=HL.W; 6.1285 + break; 6.1286 + case 0xea: 6.1287 + // LD (NNNN),A 6.1288 + tempRegister.B.B0=gbReadOpcode(PC.W++); 6.1289 + tempRegister.B.B1=gbReadOpcode(PC.W++); 6.1290 + gbWriteMemory(tempRegister.W,AF.B.B1); 6.1291 + break; 6.1292 + // EB illegal 6.1293 + // EC illegal 6.1294 + // ED illegal 6.1295 + case 0xee: 6.1296 + // XOR NN 6.1297 + tempValue=gbReadOpcode(PC.W++); 6.1298 + AF.B.B1^=tempValue; 6.1299 + AF.B.B0=ZeroTable[AF.B.B1]; 6.1300 + break; 6.1301 + case 0xef: 6.1302 + // RST 28 6.1303 + gbWriteMemory(--SP.W,PC.B.B1); 6.1304 + gbWriteMemory(--SP.W,PC.B.B0); 6.1305 + PC.W=0x0028; 6.1306 + break; 6.1307 + case 0xf0: 6.1308 + // LD A,(FF00+NN) 6.1309 + AF.B.B1 = gbReadMemory(0xff00+gbReadOpcode(PC.W++)); 6.1310 + break; 6.1311 + case 0xf1: 6.1312 + // POP AF 6.1313 + AF.B.B0=gbReadMemory(SP.W++); 6.1314 + AF.B.B1=gbReadMemory(SP.W++); 6.1315 + break; 6.1316 + case 0xf2: 6.1317 + // LD A,(FF00+C) 6.1318 + AF.B.B1 = gbReadMemory(0xff00+BC.B.B0); 6.1319 + break; 6.1320 + case 0xf3: 6.1321 + // DI 6.1322 + // IFF&=0xFE; 6.1323 + IFF&=(~0x21); 6.1324 + break; 6.1325 + // F4 illegal 6.1326 + case 0xf5: 6.1327 + // PUSH AF 6.1328 + gbWriteMemory(--SP.W,AF.B.B1); 6.1329 + gbWriteMemory(--SP.W,AF.B.B0); 6.1330 + break; 6.1331 + case 0xf6: 6.1332 + // OR NN 6.1333 + tempValue=gbReadOpcode(PC.W++); 6.1334 + AF.B.B1|=tempValue; 6.1335 + AF.B.B0=ZeroTable[AF.B.B1]; 6.1336 + break; 6.1337 + case 0xf7: 6.1338 + // RST 30 6.1339 + gbWriteMemory(--SP.W,PC.B.B1); 6.1340 + gbWriteMemory(--SP.W,PC.B.B0); 6.1341 + PC.W=0x0030; 6.1342 + break; 6.1343 + case 0xf8: 6.1344 + // LD HL,SP+NN 6.1345 + offset = (s8)gbReadOpcode(PC.W++); 6.1346 + if(offset >= 0) { 6.1347 + tempRegister.W = SP.W + offset; 6.1348 + AF.B.B0 = (SP.W > tempRegister.W ? C_FLAG : 0) | 6.1349 + ((SP.W^offset^tempRegister.W)&0x1000? H_FLAG:0); 6.1350 + HL.W = tempRegister.W; 6.1351 + } else { 6.1352 + tempRegister.W = SP.W + offset; 6.1353 + AF.B.B0 = (SP.W < tempRegister.W ? C_FLAG : 0) | 6.1354 + ((SP.W^offset^tempRegister.W)&0x1000?H_FLAG:0); 6.1355 + HL.W = tempRegister.W; 6.1356 + } 6.1357 + break; 6.1358 + case 0xf9: 6.1359 + // LD SP,HL 6.1360 + SP.W=HL.W; 6.1361 + break; 6.1362 + case 0xfa: 6.1363 + // LD A,(NNNN) 6.1364 + tempRegister.B.B0=gbReadOpcode(PC.W++); 6.1365 + tempRegister.B.B1=gbReadOpcode(PC.W++); 6.1366 + AF.B.B1=gbReadMemory(tempRegister.W); 6.1367 + break; 6.1368 + case 0xfb: 6.1369 + // EI 6.1370 + IFF|=0x20; 6.1371 + break; 6.1372 + // FC illegal 6.1373 + // FD illegal 6.1374 + case 0xfe: 6.1375 + // CP NN 6.1376 + tempValue=gbReadOpcode(PC.W++); 6.1377 + tempRegister.W=AF.B.B1-tempValue; 6.1378 + AF.B.B0= N_FLAG|(tempRegister.B.B1?C_FLAG:0)|ZeroTable[tempRegister.B.B0]| 6.1379 + ((AF.B.B1^tempValue^tempRegister.B.B0)&0x10?H_FLAG:0); 6.1380 + break; 6.1381 + case 0xff: 6.1382 + // RST 38 6.1383 + gbWriteMemory(--SP.W,PC.B.B1); 6.1384 + gbWriteMemory(--SP.W,PC.B.B0); 6.1385 + PC.W=0x0038; 6.1386 + break; 6.1387 + default: 6.1388 + systemMessage(0, N_("Unknown opcode %02x at %04x"), 6.1389 + gbReadOpcode(PC.W-1),PC.W-1); 6.1390 + emulating = false; 6.1391 + return;
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/src/gb/gbCodesCB.h Sat Mar 03 11:44:47 2012 -0600 7.3 @@ -0,0 +1,1269 @@ 7.4 + case 0x00: 7.5 + // RLC B 7.6 + AF.B.B0 = (BC.B.B1 & 0x80)?C_FLAG:0; 7.7 + BC.B.B1 = ((BC.B.B1<<1) | (BC.B.B1>>7)) & 0xFF; 7.8 + AF.B.B0 |= ZeroTable[BC.B.B1]; 7.9 + break; 7.10 + case 0x01: 7.11 + // RLC C 7.12 + AF.B.B0 = (BC.B.B0 & 0x80)?C_FLAG:0; 7.13 + BC.B.B0 = ((BC.B.B0<<1) | (BC.B.B0>>7)) & 0xFF; 7.14 + AF.B.B0 |= ZeroTable[BC.B.B0]; 7.15 + break; 7.16 + case 0x02: 7.17 + // RLC D 7.18 + AF.B.B0 = (DE.B.B1 & 0x80)?C_FLAG:0; 7.19 + DE.B.B1 = ((DE.B.B1<<1) | (DE.B.B1>>7)) & 0xFF; 7.20 + AF.B.B0 |= ZeroTable[DE.B.B1]; 7.21 + break; 7.22 + case 0x03: 7.23 + // RLC E 7.24 + AF.B.B0 = (DE.B.B0 & 0x80)?C_FLAG:0; 7.25 + DE.B.B0 = ((DE.B.B0<<1) | (DE.B.B0>>7)) & 0xFF; 7.26 + AF.B.B0 |= ZeroTable[DE.B.B0]; 7.27 + break; 7.28 + case 0x04: 7.29 + // RLC H 7.30 + AF.B.B0 = (HL.B.B1 & 0x80)?C_FLAG:0; 7.31 + HL.B.B1 = ((HL.B.B1<<1) | (HL.B.B1>>7)) & 0xFF; 7.32 + AF.B.B0 |= ZeroTable[HL.B.B1]; 7.33 + break; 7.34 + case 0x05: 7.35 + // RLC L 7.36 + AF.B.B0 = (HL.B.B0 & 0x80)?C_FLAG:0; 7.37 + HL.B.B0 = ((HL.B.B0<<1) | (HL.B.B0>>7)) & 0xFF; 7.38 + AF.B.B0 |= ZeroTable[HL.B.B0]; 7.39 + break; 7.40 + case 0x06: 7.41 + // RLC (HL) 7.42 + tempValue=gbReadMemory(HL.W); 7.43 + AF.B.B0 = (tempValue & 0x80)?C_FLAG:0; 7.44 + tempValue = ((tempValue<<1) | (tempValue>>7)) & 0xFF; 7.45 + AF.B.B0 |= ZeroTable[tempValue]; 7.46 + gbWriteMemory(HL.W,tempValue); 7.47 + break; 7.48 + case 0x07: 7.49 + // RLC A 7.50 + AF.B.B0 = (AF.B.B1 & 0x80)?C_FLAG:0; 7.51 + AF.B.B1 = ((AF.B.B1<<1) | (AF.B.B1>>7)) & 0xFF; 7.52 + AF.B.B0 |= ZeroTable[AF.B.B1]; 7.53 + break; 7.54 + case 0x08: 7.55 + // RRC B 7.56 + AF.B.B0=(BC.B.B1&0x01 ? C_FLAG : 0); 7.57 + BC.B.B1=((BC.B.B1>>1)|(BC.B.B1<<7)) & 0xFF; 7.58 + AF.B.B0|=ZeroTable[BC.B.B1]; 7.59 + break; 7.60 + case 0x09: 7.61 + // RRC C 7.62 + AF.B.B0=(BC.B.B0&0x01 ? C_FLAG : 0); 7.63 + BC.B.B0=((BC.B.B0>>1)|(BC.B.B0<<7)) & 0xFF; 7.64 + AF.B.B0|=ZeroTable[BC.B.B0]; 7.65 + break; 7.66 + case 0x0a: 7.67 + // RRC D 7.68 + AF.B.B0=(DE.B.B1&0x01 ? C_FLAG : 0); 7.69 + DE.B.B1=((DE.B.B1>>1)|(DE.B.B1<<7)) & 0xFF; 7.70 + AF.B.B0|=ZeroTable[DE.B.B1]; 7.71 + break; 7.72 + case 0x0b: 7.73 + // RRC E 7.74 + AF.B.B0=(DE.B.B0&0x01 ? C_FLAG : 0); 7.75 + DE.B.B0=((DE.B.B0>>1)|(DE.B.B0<<7)) & 0xFF; 7.76 + AF.B.B0|=ZeroTable[DE.B.B0]; 7.77 + break; 7.78 + case 0x0c: 7.79 + // RRC H 7.80 + AF.B.B0=(HL.B.B1&0x01 ? C_FLAG : 0); 7.81 + HL.B.B1=((HL.B.B1>>1)|(HL.B.B1<<7)) & 0xFF; 7.82 + AF.B.B0|=ZeroTable[HL.B.B1]; 7.83 + break; 7.84 + case 0x0d: 7.85 + // RRC L 7.86 + AF.B.B0=(HL.B.B0&0x01 ? C_FLAG : 0); 7.87 + HL.B.B0=((HL.B.B0>>1)|(HL.B.B0<<7)) & 0xFF; 7.88 + AF.B.B0|=ZeroTable[HL.B.B0]; 7.89 + break; 7.90 + case 0x0e: 7.91 + // RRC (HL) 7.92 + tempValue=gbReadMemory(HL.W); 7.93 + AF.B.B0=(tempValue&0x01 ? C_FLAG : 0); 7.94 + tempValue=((tempValue>>1)|(tempValue<<7)) & 0xFF; 7.95 + AF.B.B0|=ZeroTable[tempValue]; 7.96 + gbWriteMemory(HL.W,tempValue); 7.97 + break; 7.98 + case 0x0f: 7.99 + // RRC A 7.100 + AF.B.B0=(AF.B.B1&0x01 ? C_FLAG : 0); 7.101 + AF.B.B1=((AF.B.B1>>1)|(AF.B.B1<<7)) & 0xFF; 7.102 + AF.B.B0|=ZeroTable[AF.B.B1]; 7.103 + break; 7.104 + case 0x10: 7.105 + // RL B 7.106 + if(BC.B.B1&0x80) { 7.107 + BC.B.B1=((BC.B.B1<<1)|(AF.B.B0&C_FLAG ? 1 : 0)) & 0xFF; 7.108 + AF.B.B0=ZeroTable[BC.B.B1]|C_FLAG; 7.109 + } else { 7.110 + BC.B.B1=((BC.B.B1<<1)|(AF.B.B0&C_FLAG ? 1 : 0)) & 0xFF; 7.111 + AF.B.B0=ZeroTable[BC.B.B1]; 7.112 + } 7.113 + break; 7.114 + case 0x11: 7.115 + // RL C 7.116 + if(BC.B.B0&0x80) { 7.117 + BC.B.B0=((BC.B.B0<<1)|(AF.B.B0&C_FLAG ? 1 : 0)) & 0xFF; 7.118 + AF.B.B0=ZeroTable[BC.B.B0]|C_FLAG; 7.119 + } else { 7.120 + BC.B.B0=((BC.B.B0<<1)|(AF.B.B0&C_FLAG ? 1 : 0)) & 0xFF; 7.121 + AF.B.B0=ZeroTable[BC.B.B0]; 7.122 + } 7.123 + break; 7.124 + case 0x12: 7.125 + // RL D 7.126 + if(DE.B.B1&0x80) { 7.127 + DE.B.B1=((DE.B.B1<<1)|(AF.B.B0&C_FLAG ? 1 : 0)) & 0xFF; 7.128 + AF.B.B0=ZeroTable[DE.B.B1]|C_FLAG; 7.129 + } else { 7.130 + DE.B.B1=((DE.B.B1<<1)|(AF.B.B0&C_FLAG ? 1 : 0)) & 0xFF; 7.131 + AF.B.B0=ZeroTable[DE.B.B1]; 7.132 + } 7.133 + break; 7.134 + case 0x13: 7.135 + // RL E 7.136 + if(DE.B.B0&0x80) { 7.137 + DE.B.B0=((DE.B.B0<<1)|(AF.B.B0&C_FLAG ? 1 : 0)) & 0xFF; 7.138 + AF.B.B0=ZeroTable[DE.B.B0]|C_FLAG; 7.139 + } else { 7.140 + DE.B.B0=((DE.B.B0<<1)|(AF.B.B0&C_FLAG ? 1 : 0)) & 0xFF; 7.141 + AF.B.B0=ZeroTable[DE.B.B0]; 7.142 + } 7.143 + break; 7.144 + case 0x14: 7.145 + // RL H 7.146 + if(HL.B.B1&0x80) { 7.147 + HL.B.B1=((HL.B.B1<<1)|(AF.B.B0&C_FLAG ? 1 : 0)) & 0xFF; 7.148 + AF.B.B0=ZeroTable[HL.B.B1]|C_FLAG; 7.149 + } else { 7.150 + HL.B.B1=((HL.B.B1<<1)|(AF.B.B0&C_FLAG ? 1 : 0)) & 0xFF; 7.151 + AF.B.B0=ZeroTable[HL.B.B1]; 7.152 + } 7.153 + break; 7.154 + case 0x15: 7.155 + // RL L 7.156 + if(HL.B.B0&0x80) { 7.157 + HL.B.B0=((HL.B.B0<<1)|(AF.B.B0&C_FLAG ? 1 : 0)) & 0xFF; 7.158 + AF.B.B0=ZeroTable[HL.B.B0]|C_FLAG; 7.159 + } else { 7.160 + HL.B.B0=((HL.B.B0<<1)|(AF.B.B0&C_FLAG ? 1 : 0)) & 0xFF; 7.161 + AF.B.B0=ZeroTable[HL.B.B0]; 7.162 + } 7.163 + break; 7.164 + case 0x16: 7.165 + // RL (HL) 7.166 + tempValue=gbReadMemory(HL.W); 7.167 + if(tempValue&0x80) { 7.168 + tempValue=((tempValue<<1)|(AF.B.B0&C_FLAG ? 1 : 0)) & 0xFF; 7.169 + AF.B.B0=ZeroTable[tempValue]|C_FLAG; 7.170 + } else { 7.171 + tempValue=((tempValue<<1)|(AF.B.B0&C_FLAG ? 1 : 0)) & 0xFF; 7.172 + AF.B.B0=ZeroTable[tempValue]; 7.173 + } 7.174 + gbWriteMemory(HL.W,tempValue); 7.175 + break; 7.176 + case 0x17: 7.177 + // RL A 7.178 + if(AF.B.B1&0x80) { 7.179 + AF.B.B1=((AF.B.B1<<1)|(AF.B.B0&C_FLAG ? 1 : 0)) & 0xFF; 7.180 + AF.B.B0=ZeroTable[AF.B.B1]|C_FLAG; 7.181 + } else { 7.182 + AF.B.B1=((AF.B.B1<<1)|(AF.B.B0&C_FLAG ? 1 : 0)) & 0xFF; 7.183 + AF.B.B0=ZeroTable[AF.B.B1]; 7.184 + } 7.185 + break; 7.186 + case 0x18: 7.187 + // RR B 7.188 + if(BC.B.B1&0x01) { 7.189 + BC.B.B1=(BC.B.B1>>1)|(AF.B.B0 & C_FLAG ? 0x80:0); 7.190 + AF.B.B0=ZeroTable[BC.B.B1]|C_FLAG; 7.191 + } else { 7.192 + BC.B.B1=(BC.B.B1>>1)|(AF.B.B0 & C_FLAG ? 0x80:0); 7.193 + AF.B.B0=ZeroTable[BC.B.B1]; 7.194 + } 7.195 + break; 7.196 + case 0x19: 7.197 + // RR C 7.198 + if(BC.B.B0&0x01) { 7.199 + BC.B.B0=(BC.B.B0>>1)|(AF.B.B0 & C_FLAG ? 0x80:0); 7.200 + AF.B.B0=ZeroTable[BC.B.B0]|C_FLAG; 7.201 + } else { 7.202 + BC.B.B0=(BC.B.B0>>1)|(AF.B.B0 & C_FLAG ? 0x80:0); 7.203 + AF.B.B0=ZeroTable[BC.B.B0]; 7.204 + } 7.205 + break; 7.206 + case 0x1a: 7.207 + // RR D 7.208 + if(DE.B.B1&0x01) { 7.209 + DE.B.B1=(DE.B.B1>>1)|(AF.B.B0 & C_FLAG ? 0x80:0); 7.210 + AF.B.B0=ZeroTable[DE.B.B1]|C_FLAG; 7.211 + } else { 7.212 + DE.B.B1=(DE.B.B1>>1)|(AF.B.B0 & C_FLAG ? 0x80:0); 7.213 + AF.B.B0=ZeroTable[DE.B.B1]; 7.214 + } 7.215 + break; 7.216 + case 0x1b: 7.217 + // RR E 7.218 + if(DE.B.B0&0x01) { 7.219 + DE.B.B0=(DE.B.B0>>1)|(AF.B.B0 & C_FLAG ? 0x80:0); 7.220 + AF.B.B0=ZeroTable[DE.B.B0]|C_FLAG; 7.221 + } else { 7.222 + DE.B.B0=(DE.B.B0>>1)|(AF.B.B0 & C_FLAG ? 0x80:0); 7.223 + AF.B.B0=ZeroTable[DE.B.B0]; 7.224 + } 7.225 + break; 7.226 + case 0x1c: 7.227 + // RR H 7.228 + if(HL.B.B1&0x01) { 7.229 + HL.B.B1=(HL.B.B1>>1)|(AF.B.B0 & C_FLAG ? 0x80:0); 7.230 + AF.B.B0=ZeroTable[HL.B.B1]|C_FLAG; 7.231 + } else { 7.232 + HL.B.B1=(HL.B.B1>>1)|(AF.B.B0 & C_FLAG ? 0x80:0); 7.233 + AF.B.B0=ZeroTable[HL.B.B1]; 7.234 + } 7.235 + break; 7.236 + case 0x1d: 7.237 + // RR L 7.238 + if(HL.B.B0&0x01) { 7.239 + HL.B.B0=(HL.B.B0>>1)|(AF.B.B0 & C_FLAG ? 0x80:0); 7.240 + AF.B.B0=ZeroTable[HL.B.B0]|C_FLAG; 7.241 + } else { 7.242 + HL.B.B0=(HL.B.B0>>1)|(AF.B.B0 & C_FLAG ? 0x80:0); 7.243 + AF.B.B0=ZeroTable[HL.B.B0]; 7.244 + } 7.245 + break; 7.246 + case 0x1e: 7.247 + // RR (HL) 7.248 + tempValue=gbReadMemory(HL.W); 7.249 + if(tempValue&0x01) { 7.250 + tempValue=(tempValue>>1)|(AF.B.B0 & C_FLAG ? 0x80:0); 7.251 + AF.B.B0=ZeroTable[tempValue]|C_FLAG; 7.252 + } else { 7.253 + tempValue=(tempValue>>1)|(AF.B.B0 & C_FLAG ? 0x80:0); 7.254 + AF.B.B0=ZeroTable[tempValue]; 7.255 + } 7.256 + gbWriteMemory(HL.W,tempValue); 7.257 + break; 7.258 + case 0x1f: 7.259 + // RR A 7.260 + if(AF.B.B1&0x01) { 7.261 + AF.B.B1=(AF.B.B1>>1)|(AF.B.B0 & C_FLAG ? 0x80:0); 7.262 + AF.B.B0=ZeroTable[AF.B.B1]|C_FLAG; 7.263 + } else { 7.264 + AF.B.B1=(AF.B.B1>>1)|(AF.B.B0 & C_FLAG ? 0x80:0); 7.265 + AF.B.B0=ZeroTable[AF.B.B1]; 7.266 + } 7.267 + break; 7.268 + case 0x20: 7.269 + // SLA B 7.270 + AF.B.B0=(BC.B.B1&0x80?C_FLAG : 0); 7.271 + BC.B.B1<<=1; 7.272 + AF.B.B0|=ZeroTable[BC.B.B1]; 7.273 + break; 7.274 + case 0x21: 7.275 + // SLA C 7.276 + AF.B.B0=(BC.B.B0&0x80?C_FLAG : 0); 7.277 + BC.B.B0<<=1; 7.278 + AF.B.B0|=ZeroTable[BC.B.B0]; 7.279 + break; 7.280 + case 0x22: 7.281 + // SLA D 7.282 + AF.B.B0=(DE.B.B1&0x80?C_FLAG : 0); 7.283 + DE.B.B1<<=1; 7.284 + AF.B.B0|=ZeroTable[DE.B.B1]; 7.285 + break; 7.286 + case 0x23: 7.287 + // SLA E 7.288 + AF.B.B0=(DE.B.B0&0x80?C_FLAG : 0); 7.289 + DE.B.B0<<=1; 7.290 + AF.B.B0|=ZeroTable[DE.B.B0]; 7.291 + break; 7.292 + case 0x24: 7.293 + // SLA H 7.294 + AF.B.B0=(HL.B.B1&0x80?C_FLAG : 0); 7.295 + HL.B.B1<<=1; 7.296 + AF.B.B0|=ZeroTable[HL.B.B1]; 7.297 + break; 7.298 + case 0x25: 7.299 + // SLA L 7.300 + AF.B.B0=(HL.B.B0&0x80?C_FLAG : 0); 7.301 + HL.B.B0<<=1; 7.302 + AF.B.B0|=ZeroTable[HL.B.B0]; 7.303 + break; 7.304 + case 0x26: 7.305 + // SLA (HL) 7.306 + tempValue=gbReadMemory(HL.W); 7.307 + AF.B.B0=(tempValue&0x80?C_FLAG : 0); 7.308 + tempValue<<=1; 7.309 + AF.B.B0|=ZeroTable[tempValue]; 7.310 + gbWriteMemory(HL.W,tempValue); 7.311 + break; 7.312 + case 0x27: 7.313 + // SLA A 7.314 + AF.B.B0=(AF.B.B1&0x80?C_FLAG : 0); 7.315 + AF.B.B1<<=1; 7.316 + AF.B.B0|=ZeroTable[AF.B.B1]; 7.317 + break; 7.318 + case 0x28: 7.319 + // SRA B 7.320 + AF.B.B0=(BC.B.B1&0x01 ? C_FLAG: 0); 7.321 + BC.B.B1=(BC.B.B1>>1)|(BC.B.B1&0x80); 7.322 + AF.B.B0|=ZeroTable[BC.B.B1]; 7.323 + break; 7.324 + case 0x29: 7.325 + // SRA C 7.326 + AF.B.B0=(BC.B.B0&0x01 ? C_FLAG: 0); 7.327 + BC.B.B0=(BC.B.B0>>1)|(BC.B.B0&0x80); 7.328 + AF.B.B0|=ZeroTable[BC.B.B0]; 7.329 + break; 7.330 + case 0x2a: 7.331 + // SRA D 7.332 + AF.B.B0=(DE.B.B1&0x01 ? C_FLAG: 0); 7.333 + DE.B.B1=(DE.B.B1>>1)|(DE.B.B1&0x80); 7.334 + AF.B.B0|=ZeroTable[DE.B.B1]; 7.335 + break; 7.336 + case 0x2b: 7.337 + // SRA E 7.338 + AF.B.B0=(DE.B.B0&0x01 ? C_FLAG: 0); 7.339 + DE.B.B0=(DE.B.B0>>1)|(DE.B.B0&0x80); 7.340 + AF.B.B0|=ZeroTable[DE.B.B0]; 7.341 + break; 7.342 + case 0x2c: 7.343 + // SRA H 7.344 + AF.B.B0=(HL.B.B1&0x01 ? C_FLAG: 0); 7.345 + HL.B.B1=(HL.B.B1>>1)|(HL.B.B1&0x80); 7.346 + AF.B.B0|=ZeroTable[HL.B.B1]; 7.347 + break; 7.348 + case 0x2d: 7.349 + // SRA L 7.350 + AF.B.B0=(HL.B.B0&0x01 ? C_FLAG: 0); 7.351 + HL.B.B0=(HL.B.B0>>1)|(HL.B.B0&0x80); 7.352 + AF.B.B0|=ZeroTable[HL.B.B0]; 7.353 + break; 7.354 + case 0x2e: 7.355 + // SRA (HL) 7.356 + tempValue=gbReadMemory(HL.W); 7.357 + AF.B.B0=(tempValue&0x01 ? C_FLAG: 0); 7.358 + tempValue=(tempValue>>1)|(tempValue&0x80); 7.359 + AF.B.B0|=ZeroTable[tempValue]; 7.360 + gbWriteMemory(HL.W,tempValue); 7.361 + break; 7.362 + case 0x2f: 7.363 + // SRA A 7.364 + AF.B.B0=(AF.B.B1&0x01 ? C_FLAG: 0); 7.365 + AF.B.B1=(AF.B.B1>>1)|(AF.B.B1&0x80); 7.366 + AF.B.B0|=ZeroTable[AF.B.B1]; 7.367 + break; 7.368 + case 0x30: 7.369 + // SWAP B 7.370 + BC.B.B1 = (BC.B.B1&0xf0)>>4 | (BC.B.B1&0x0f)<<4; 7.371 + AF.B.B0 = ZeroTable[BC.B.B1]; 7.372 + break; 7.373 + case 0x31: 7.374 + // SWAP C 7.375 + BC.B.B0 = (BC.B.B0&0xf0)>>4 | (BC.B.B0&0x0f)<<4; 7.376 + AF.B.B0 = ZeroTable[BC.B.B0]; 7.377 + break; 7.378 + case 0x32: 7.379 + // SWAP D 7.380 + DE.B.B1 = (DE.B.B1&0xf0)>>4 | (DE.B.B1&0x0f)<<4; 7.381 + AF.B.B0 = ZeroTable[DE.B.B1]; 7.382 + break; 7.383 + case 0x33: 7.384 + // SWAP E 7.385 + DE.B.B0 = (DE.B.B0&0xf0)>>4 | (DE.B.B0&0x0f)<<4; 7.386 + AF.B.B0 = ZeroTable[DE.B.B0]; 7.387 + break; 7.388 + case 0x34: 7.389 + // SWAP H 7.390 + HL.B.B1 = (HL.B.B1&0xf0)>>4 | (HL.B.B1&0x0f)<<4; 7.391 + AF.B.B0 = ZeroTable[HL.B.B1]; 7.392 + break; 7.393 + case 0x35: 7.394 + // SWAP L 7.395 + HL.B.B0 = (HL.B.B0&0xf0)>>4 | (HL.B.B0&0x0f)<<4; 7.396 + AF.B.B0 = ZeroTable[HL.B.B0]; 7.397 + break; 7.398 + case 0x36: 7.399 + // SWAP (HL) 7.400 + tempValue=gbReadMemory(HL.W); 7.401 + tempValue = (tempValue&0xf0)>>4 | (tempValue&0x0f)<<4; 7.402 + AF.B.B0 = ZeroTable[tempValue]; 7.403 + gbWriteMemory(HL.W,tempValue); 7.404 + break; 7.405 + case 0x37: 7.406 + // SWAP A 7.407 + AF.B.B1 = (AF.B.B1&0xf0)>>4 | (AF.B.B1&0x0f)<<4; 7.408 + AF.B.B0 = ZeroTable[AF.B.B1]; 7.409 + break; 7.410 + case 0x38: 7.411 + // SRL B 7.412 + AF.B.B0=(BC.B.B1&0x01)?C_FLAG:0; 7.413 + BC.B.B1>>=1; 7.414 + AF.B.B0|=ZeroTable[BC.B.B1]; 7.415 + break; 7.416 + case 0x39: 7.417 + // SRL C 7.418 + AF.B.B0=(BC.B.B0&0x01)?C_FLAG:0; 7.419 + BC.B.B0>>=1; 7.420 + AF.B.B0|=ZeroTable[BC.B.B0]; 7.421 + break; 7.422 + case 0x3a: 7.423 + // SRL D 7.424 + AF.B.B0=(DE.B.B1&0x01)?C_FLAG:0; 7.425 + DE.B.B1>>=1; 7.426 + AF.B.B0|=ZeroTable[DE.B.B1]; 7.427 + break; 7.428 + case 0x3b: 7.429 + // SRL E 7.430 + AF.B.B0=(DE.B.B0&0x01)?C_FLAG:0; 7.431 + DE.B.B0>>=1; 7.432 + AF.B.B0|=ZeroTable[DE.B.B0]; 7.433 + break; 7.434 + case 0x3c: 7.435 + // SRL H 7.436 + AF.B.B0=(HL.B.B1&0x01)?C_FLAG:0; 7.437 + HL.B.B1>>=1; 7.438 + AF.B.B0|=ZeroTable[HL.B.B1]; 7.439 + break; 7.440 + case 0x3d: 7.441 + // SRL L 7.442 + AF.B.B0=(HL.B.B0&0x01)?C_FLAG:0; 7.443 + HL.B.B0>>=1; 7.444 + AF.B.B0|=ZeroTable[HL.B.B0]; 7.445 + break; 7.446 + case 0x3e: 7.447 + // SRL (HL) 7.448 + tempValue=gbReadMemory(HL.W); 7.449 + AF.B.B0=(tempValue&0x01)?C_FLAG:0; 7.450 + tempValue>>=1; 7.451 + AF.B.B0|=ZeroTable[tempValue]; 7.452 + gbWriteMemory(HL.W,tempValue); 7.453 + break; 7.454 + case 0x3f: 7.455 + // SRL A 7.456 + AF.B.B0=(AF.B.B1&0x01)?C_FLAG:0; 7.457 + AF.B.B1>>=1; 7.458 + AF.B.B0|=ZeroTable[AF.B.B1]; 7.459 + break; 7.460 + case 0x40: 7.461 + // BIT 0,B 7.462 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(BC.B.B1&(1<<0)? 0:Z_FLAG); 7.463 + break; 7.464 + case 0x41: 7.465 + // BIT 0,C 7.466 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(BC.B.B0&(1<<0)? 0:Z_FLAG); 7.467 + break; 7.468 + case 0x42: 7.469 + // BIT 0,D 7.470 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(DE.B.B1&(1<<0)? 0:Z_FLAG); 7.471 + break; 7.472 + case 0x43: 7.473 + // BIT 0,E 7.474 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(DE.B.B0&(1<<0)? 0:Z_FLAG); 7.475 + break; 7.476 + case 0x44: 7.477 + // BIT 0,H 7.478 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(HL.B.B1&(1<<0)? 0:Z_FLAG); 7.479 + break; 7.480 + case 0x45: 7.481 + // BIT 0,L 7.482 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(HL.B.B0&(1<<0)? 0:Z_FLAG); 7.483 + break; 7.484 + case 0x46: 7.485 + // BIT 0,(HL) 7.486 + tempValue=gbReadMemory(HL.W); 7.487 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(tempValue&(1<<0)? 0:Z_FLAG); 7.488 + break; 7.489 + case 0x47: 7.490 + // BIT 0,A 7.491 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(AF.B.B1&(1<<0)? 0:Z_FLAG); 7.492 + break; 7.493 + case 0x48: 7.494 + // BIT 1,B 7.495 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(BC.B.B1&(1<<1)? 0:Z_FLAG); 7.496 + break; 7.497 + case 0x49: 7.498 + // BIT 1,C 7.499 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(BC.B.B0&(1<<1)? 0:Z_FLAG); 7.500 + break; 7.501 + case 0x4a: 7.502 + // BIT 1,D 7.503 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(DE.B.B1&(1<<1)? 0:Z_FLAG); 7.504 + break; 7.505 + case 0x4b: 7.506 + // BIT 1,E 7.507 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(DE.B.B0&(1<<1)? 0:Z_FLAG); 7.508 + break; 7.509 + case 0x4c: 7.510 + // BIT 1,H 7.511 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(HL.B.B1&(1<<1)? 0:Z_FLAG); 7.512 + break; 7.513 + case 0x4d: 7.514 + // BIT 1,L 7.515 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(HL.B.B0&(1<<1)? 0:Z_FLAG); 7.516 + break; 7.517 + case 0x4e: 7.518 + // BIT 1,(HL) 7.519 + tempValue=gbReadMemory(HL.W); 7.520 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(tempValue&(1<<1)? 0:Z_FLAG); 7.521 + break; 7.522 + case 0x4f: 7.523 + // BIT 1,A 7.524 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(AF.B.B1&(1<<1)? 0:Z_FLAG); 7.525 + break; 7.526 + case 0x50: 7.527 + // BIT 2,B 7.528 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(BC.B.B1&(1<<2)? 0:Z_FLAG); 7.529 + break; 7.530 + case 0x51: 7.531 + // BIT 2,C 7.532 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(BC.B.B0&(1<<2)? 0:Z_FLAG); 7.533 + break; 7.534 + case 0x52: 7.535 + // BIT 2,D 7.536 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(DE.B.B1&(1<<2)? 0:Z_FLAG); 7.537 + break; 7.538 + case 0x53: 7.539 + // BIT 2,E 7.540 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(DE.B.B0&(1<<2)? 0:Z_FLAG); 7.541 + break; 7.542 + case 0x54: 7.543 + // BIT 2,H 7.544 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(HL.B.B1&(1<<2)? 0:Z_FLAG); 7.545 + break; 7.546 + case 0x55: 7.547 + // BIT 2,L 7.548 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(HL.B.B0&(1<<2)? 0:Z_FLAG); 7.549 + break; 7.550 + case 0x56: 7.551 + // BIT 2,(HL) 7.552 + tempValue=gbReadMemory(HL.W); 7.553 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(tempValue&(1<<2)? 0:Z_FLAG); 7.554 + break; 7.555 + case 0x57: 7.556 + // BIT 2,A 7.557 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(AF.B.B1&(1<<2)? 0:Z_FLAG); 7.558 + break; 7.559 + case 0x58: 7.560 + // BIT 3,B 7.561 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(BC.B.B1&(1<<3)? 0:Z_FLAG); 7.562 + break; 7.563 + case 0x59: 7.564 + // BIT 3,C 7.565 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(BC.B.B0&(1<<3)? 0:Z_FLAG); 7.566 + break; 7.567 + case 0x5a: 7.568 + // BIT 3,D 7.569 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(DE.B.B1&(1<<3)? 0:Z_FLAG); 7.570 + break; 7.571 + case 0x5b: 7.572 + // BIT 3,E 7.573 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(DE.B.B0&(1<<3)? 0:Z_FLAG); 7.574 + break; 7.575 + case 0x5c: 7.576 + // BIT 3,H 7.577 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(HL.B.B1&(1<<3)? 0:Z_FLAG); 7.578 + break; 7.579 + case 0x5d: 7.580 + // BIT 3,L 7.581 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(HL.B.B0&(1<<3)? 0:Z_FLAG); 7.582 + break; 7.583 + case 0x5e: 7.584 + // BIT 3,(HL) 7.585 + tempValue=gbReadMemory(HL.W); 7.586 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(tempValue&(1<<3)? 0:Z_FLAG); 7.587 + break; 7.588 + case 0x5f: 7.589 + // BIT 3,A 7.590 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(AF.B.B1&(1<<3)? 0:Z_FLAG); 7.591 + break; 7.592 + case 0x60: 7.593 + // BIT 4,B 7.594 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(BC.B.B1&(1<<4)? 0:Z_FLAG); 7.595 + break; 7.596 + case 0x61: 7.597 + // BIT 4,C 7.598 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(BC.B.B0&(1<<4)? 0:Z_FLAG); 7.599 + break; 7.600 + case 0x62: 7.601 + // BIT 4,D 7.602 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(DE.B.B1&(1<<4)? 0:Z_FLAG); 7.603 + break; 7.604 + case 0x63: 7.605 + // BIT 4,E 7.606 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(DE.B.B0&(1<<4)? 0:Z_FLAG); 7.607 + break; 7.608 + case 0x64: 7.609 + // BIT 4,H 7.610 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(HL.B.B1&(1<<4)? 0:Z_FLAG); 7.611 + break; 7.612 + case 0x65: 7.613 + // BIT 4,L 7.614 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(HL.B.B0&(1<<4)? 0:Z_FLAG); 7.615 + break; 7.616 + case 0x66: 7.617 + // BIT 4,(HL) 7.618 + tempValue=gbReadMemory(HL.W); 7.619 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(tempValue&(1<<4)? 0:Z_FLAG); 7.620 + break; 7.621 + case 0x67: 7.622 + // BIT 4,A 7.623 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(AF.B.B1&(1<<4)? 0:Z_FLAG); 7.624 + break; 7.625 + case 0x68: 7.626 + // BIT 5,B 7.627 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(BC.B.B1&(1<<5)? 0:Z_FLAG); 7.628 + break; 7.629 + case 0x69: 7.630 + // BIT 5,C 7.631 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(BC.B.B0&(1<<5)? 0:Z_FLAG); 7.632 + break; 7.633 + case 0x6a: 7.634 + // BIT 5,D 7.635 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(DE.B.B1&(1<<5)? 0:Z_FLAG); 7.636 + break; 7.637 + case 0x6b: 7.638 + // BIT 5,E 7.639 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(DE.B.B0&(1<<5)? 0:Z_FLAG); 7.640 + break; 7.641 + case 0x6c: 7.642 + // BIT 5,H 7.643 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(HL.B.B1&(1<<5)? 0:Z_FLAG); 7.644 + break; 7.645 + case 0x6d: 7.646 + // BIT 5,L 7.647 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(HL.B.B0&(1<<5)? 0:Z_FLAG); 7.648 + break; 7.649 + case 0x6e: 7.650 + // BIT 5,(HL) 7.651 + tempValue=gbReadMemory(HL.W); 7.652 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(tempValue&(1<<5)? 0:Z_FLAG); 7.653 + break; 7.654 + case 0x6f: 7.655 + // BIT 5,A 7.656 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(AF.B.B1&(1<<5)? 0:Z_FLAG); 7.657 + break; 7.658 + case 0x70: 7.659 + // BIT 6,B 7.660 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(BC.B.B1&(1<<6)? 0:Z_FLAG); 7.661 + break; 7.662 + case 0x71: 7.663 + // BIT 6,C 7.664 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(BC.B.B0&(1<<6)? 0:Z_FLAG); 7.665 + break; 7.666 + case 0x72: 7.667 + // BIT 6,D 7.668 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(DE.B.B1&(1<<6)? 0:Z_FLAG); 7.669 + break; 7.670 + case 0x73: 7.671 + // BIT 6,E 7.672 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(DE.B.B0&(1<<6)? 0:Z_FLAG); 7.673 + break; 7.674 + case 0x74: 7.675 + // BIT 6,H 7.676 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(HL.B.B1&(1<<6)? 0:Z_FLAG); 7.677 + break; 7.678 + case 0x75: 7.679 + // BIT 6,L 7.680 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(HL.B.B0&(1<<6)? 0:Z_FLAG); 7.681 + break; 7.682 + case 0x76: 7.683 + // BIT 6,(HL) 7.684 + tempValue=gbReadMemory(HL.W); 7.685 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(tempValue&(1<<6)? 0:Z_FLAG); 7.686 + break; 7.687 + case 0x77: 7.688 + // BIT 6,A 7.689 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(AF.B.B1&(1<<6)? 0:Z_FLAG); 7.690 + break; 7.691 + case 0x78: 7.692 + // BIT 7,B 7.693 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(BC.B.B1&(1<<7)? 0:Z_FLAG); 7.694 + break; 7.695 + case 0x79: 7.696 + // BIT 7,C 7.697 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(BC.B.B0&(1<<7)? 0:Z_FLAG); 7.698 + break; 7.699 + case 0x7a: 7.700 + // BIT 7,D 7.701 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(DE.B.B1&(1<<7)? 0:Z_FLAG); 7.702 + break; 7.703 + case 0x7b: 7.704 + // BIT 7,E 7.705 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(DE.B.B0&(1<<7)? 0:Z_FLAG); 7.706 + break; 7.707 + case 0x7c: 7.708 + // BIT 7,H 7.709 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(HL.B.B1&(1<<7)? 0:Z_FLAG); 7.710 + break; 7.711 + case 0x7d: 7.712 + // BIT 7,L 7.713 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(HL.B.B0&(1<<7)? 0:Z_FLAG); 7.714 + break; 7.715 + case 0x7e: 7.716 + // BIT 7,(HL) 7.717 + tempValue=gbReadMemory(HL.W); 7.718 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(tempValue&(1<<7)? 0:Z_FLAG); 7.719 + break; 7.720 + case 0x7f: 7.721 + // BIT 7,A 7.722 + AF.B.B0=(AF.B.B0&C_FLAG)|H_FLAG|(AF.B.B1&(1<<7)? 0:Z_FLAG); 7.723 + break; 7.724 + case 0x80: 7.725 + // RES 0,B 7.726 + BC.B.B1&=~(1<<0); 7.727 + break; 7.728 + case 0x81: 7.729 + // RES 0,C 7.730 + BC.B.B0&=~(1<<0); 7.731 + break; 7.732 + case 0x82: 7.733 + // RES 0,D 7.734 + DE.B.B1&=~(1<<0); 7.735 + break; 7.736 + case 0x83: 7.737 + // RES 0,E 7.738 + DE.B.B0&=~(1<<0); 7.739 + break; 7.740 + case 0x84: 7.741 + // RES 0,H 7.742 + HL.B.B1&=~(1<<0); 7.743 + break; 7.744 + case 0x85: 7.745 + // RES 0,L 7.746 + HL.B.B0&=~(1<<0); 7.747 + break; 7.748 + case 0x86: 7.749 + // RES 0,(HL) 7.750 + tempValue=gbReadMemory(HL.W); 7.751 + tempValue&=~(1<<0); 7.752 + gbWriteMemory(HL.W,tempValue); 7.753 + break; 7.754 + case 0x87: 7.755 + // RES 0,A 7.756 + AF.B.B1&=~(1<<0); 7.757 + break; 7.758 + case 0x88: 7.759 + // RES 1,B 7.760 + BC.B.B1&=~(1<<1); 7.761 + break; 7.762 + case 0x89: 7.763 + // RES 1,C 7.764 + BC.B.B0&=~(1<<1); 7.765 + break; 7.766 + case 0x8a: 7.767 + // RES 1,D 7.768 + DE.B.B1&=~(1<<1); 7.769 + break; 7.770 + case 0x8b: 7.771 + // RES 1,E 7.772 + DE.B.B0&=~(1<<1); 7.773 + break; 7.774 + case 0x8c: 7.775 + // RES 1,H 7.776 + HL.B.B1&=~(1<<1); 7.777 + break; 7.778 + case 0x8d: 7.779 + // RES 1,L 7.780 + HL.B.B0&=~(1<<1); 7.781 + break; 7.782 + case 0x8e: 7.783 + // RES 1,(HL) 7.784 + tempValue=gbReadMemory(HL.W); 7.785 + tempValue&=~(1<<1); 7.786 + gbWriteMemory(HL.W,tempValue); 7.787 + break; 7.788 + case 0x8f: 7.789 + // RES 1,A 7.790 + AF.B.B1&=~(1<<1); 7.791 + break; 7.792 + case 0x90: 7.793 + // RES 2,B 7.794 + BC.B.B1&=~(1<<2); 7.795 + break; 7.796 + case 0x91: 7.797 + // RES 2,C 7.798 + BC.B.B0&=~(1<<2); 7.799 + break; 7.800 + case 0x92: 7.801 + // RES 2,D 7.802 + DE.B.B1&=~(1<<2); 7.803 + break; 7.804 + case 0x93: 7.805 + // RES 2,E 7.806 + DE.B.B0&=~(1<<2); 7.807 + break; 7.808 + case 0x94: 7.809 + // RES 2,H 7.810 + HL.B.B1&=~(1<<2); 7.811 + break; 7.812 + case 0x95: 7.813 + // RES 2,L 7.814 + HL.B.B0&=~(1<<2); 7.815 + break; 7.816 + case 0x96: 7.817 + // RES 2,(HL) 7.818 + tempValue=gbReadMemory(HL.W); 7.819 + tempValue&=~(1<<2); 7.820 + gbWriteMemory(HL.W,tempValue); 7.821 + break; 7.822 + case 0x97: 7.823 + // RES 2,A 7.824 + AF.B.B1&=~(1<<2); 7.825 + break; 7.826 + case 0x98: 7.827 + // RES 3,B 7.828 + BC.B.B1&=~(1<<3); 7.829 + break; 7.830 + case 0x99: 7.831 + // RES 3,C 7.832 + BC.B.B0&=~(1<<3); 7.833 + break; 7.834 + case 0x9a: 7.835 + // RES 3,D 7.836 + DE.B.B1&=~(1<<3); 7.837 + break; 7.838 + case 0x9b: 7.839 + // RES 3,E 7.840 + DE.B.B0&=~(1<<3); 7.841 + break; 7.842 + case 0x9c: 7.843 + // RES 3,H 7.844 + HL.B.B1&=~(1<<3); 7.845 + break; 7.846 + case 0x9d: 7.847 + // RES 3,L 7.848 + HL.B.B0&=~(1<<3); 7.849 + break; 7.850 + case 0x9e: 7.851 + // RES 3,(HL) 7.852 + tempValue=gbReadMemory(HL.W); 7.853 + tempValue&=~(1<<3); 7.854 + gbWriteMemory(HL.W,tempValue); 7.855 + break; 7.856 + case 0x9f: 7.857 + // RES 3,A 7.858 + AF.B.B1&=~(1<<3); 7.859 + break; 7.860 + case 0xa0: 7.861 + // RES 4,B 7.862 + BC.B.B1&=~(1<<4); 7.863 + break; 7.864 + case 0xa1: 7.865 + // RES 4,C 7.866 + BC.B.B0&=~(1<<4); 7.867 + break; 7.868 + case 0xa2: 7.869 + // RES 4,D 7.870 + DE.B.B1&=~(1<<4); 7.871 + break; 7.872 + case 0xa3: 7.873 + // RES 4,E 7.874 + DE.B.B0&=~(1<<4); 7.875 + break; 7.876 + case 0xa4: 7.877 + // RES 4,H 7.878 + HL.B.B1&=~(1<<4); 7.879 + break; 7.880 + case 0xa5: 7.881 + // RES 4,L 7.882 + HL.B.B0&=~(1<<4); 7.883 + break; 7.884 + case 0xa6: 7.885 + // RES 4,(HL) 7.886 + tempValue=gbReadMemory(HL.W); 7.887 + tempValue&=~(1<<4); 7.888 + gbWriteMemory(HL.W,tempValue); 7.889 + break; 7.890 + case 0xa7: 7.891 + // RES 4,A 7.892 + AF.B.B1&=~(1<<4); 7.893 + break; 7.894 + case 0xa8: 7.895 + // RES 5,B 7.896 + BC.B.B1&=~(1<<5); 7.897 + break; 7.898 + case 0xa9: 7.899 + // RES 5,C 7.900 + BC.B.B0&=~(1<<5); 7.901 + break; 7.902 + case 0xaa: 7.903 + // RES 5,D 7.904 + DE.B.B1&=~(1<<5); 7.905 + break; 7.906 + case 0xab: 7.907 + // RES 5,E 7.908 + DE.B.B0&=~(1<<5); 7.909 + break; 7.910 + case 0xac: 7.911 + // RES 5,H 7.912 + HL.B.B1&=~(1<<5); 7.913 + break; 7.914 + case 0xad: 7.915 + // RES 5,L 7.916 + HL.B.B0&=~(1<<5); 7.917 + break; 7.918 + case 0xae: 7.919 + // RES 5,(HL) 7.920 + tempValue=gbReadMemory(HL.W); 7.921 + tempValue&=~(1<<5); 7.922 + gbWriteMemory(HL.W,tempValue); 7.923 + break; 7.924 + case 0xaf: 7.925 + // RES 5,A 7.926 + AF.B.B1&=~(1<<5); 7.927 + break; 7.928 + case 0xb0: 7.929 + // RES 6,B 7.930 + BC.B.B1&=~(1<<6); 7.931 + break; 7.932 + case 0xb1: 7.933 + // RES 6,C 7.934 + BC.B.B0&=~(1<<6); 7.935 + break; 7.936 + case 0xb2: 7.937 + // RES 6,D 7.938 + DE.B.B1&=~(1<<6); 7.939 + break; 7.940 + case 0xb3: 7.941 + // RES 6,E 7.942 + DE.B.B0&=~(1<<6); 7.943 + break; 7.944 + case 0xb4: 7.945 + // RES 6,H 7.946 + HL.B.B1&=~(1<<6); 7.947 + break; 7.948 + case 0xb5: 7.949 + // RES 6,L 7.950 + HL.B.B0&=~(1<<6); 7.951 + break; 7.952 + case 0xb6: 7.953 + // RES 6,(HL) 7.954 + tempValue=gbReadMemory(HL.W); 7.955 + tempValue&=~(1<<6); 7.956 + gbWriteMemory(HL.W,tempValue); 7.957 + break; 7.958 + case 0xb7: 7.959 + // RES 6,A 7.960 + AF.B.B1&=~(1<<6); 7.961 + break; 7.962 + case 0xb8: 7.963 + // RES 7,B 7.964 + BC.B.B1&=~(1<<7); 7.965 + break; 7.966 + case 0xb9: 7.967 + // RES 7,C 7.968 + BC.B.B0&=~(1<<7); 7.969 + break; 7.970 + case 0xba: 7.971 + // RES 7,D 7.972 + DE.B.B1&=~(1<<7); 7.973 + break; 7.974 + case 0xbb: 7.975 + // RES 7,E 7.976 + DE.B.B0&=~(1<<7); 7.977 + break; 7.978 + case 0xbc: 7.979 + // RES 7,H 7.980 + HL.B.B1&=~(1<<7); 7.981 + break; 7.982 + case 0xbd: 7.983 + // RES 7,L 7.984 + HL.B.B0&=~(1<<7); 7.985 + break; 7.986 + case 0xbe: 7.987 + // RES 7,(HL) 7.988 + tempValue=gbReadMemory(HL.W); 7.989 + tempValue&=~(1<<7); 7.990 + gbWriteMemory(HL.W,tempValue); 7.991 + break; 7.992 + case 0xbf: 7.993 + // RES 7,A 7.994 + AF.B.B1&=~(1<<7); 7.995 + break; 7.996 + case 0xc0: 7.997 + // SET 0,B 7.998 + BC.B.B1|=1<<0; 7.999 + break; 7.1000 + case 0xc1: 7.1001 + // SET 0,C 7.1002 + BC.B.B0|=1<<0; 7.1003 + break; 7.1004 + case 0xc2: 7.1005 + // SET 0,D 7.1006 + DE.B.B1|=1<<0; 7.1007 + break; 7.1008 + case 0xc3: 7.1009 + // SET 0,E 7.1010 + DE.B.B0|=1<<0; 7.1011 + break; 7.1012 + case 0xc4: 7.1013 + // SET 0,H 7.1014 + HL.B.B1|=1<<0; 7.1015 + break; 7.1016 + case 0xc5: 7.1017 + // SET 0,L 7.1018 + HL.B.B0|=1<<0; 7.1019 + break; 7.1020 + case 0xc6: 7.1021 + // SET 0,(HL) 7.1022 + tempValue=gbReadMemory(HL.W); 7.1023 + tempValue|=1<<0; 7.1024 + gbWriteMemory(HL.W,tempValue); 7.1025 + break; 7.1026 + case 0xc7: 7.1027 + // SET 0,A 7.1028 + AF.B.B1|=1<<0; 7.1029 + break; 7.1030 + case 0xc8: 7.1031 + // SET 1,B 7.1032 + BC.B.B1|=1<<1; 7.1033 + break; 7.1034 + case 0xc9: 7.1035 + // SET 1,C 7.1036 + BC.B.B0|=1<<1; 7.1037 + break; 7.1038 + case 0xca: 7.1039 + // SET 1,D 7.1040 + DE.B.B1|=1<<1; 7.1041 + break; 7.1042 + case 0xcb: 7.1043 + // SET 1,E 7.1044 + DE.B.B0|=1<<1; 7.1045 + break; 7.1046 + case 0xcc: 7.1047 + // SET 1,H 7.1048 + HL.B.B1|=1<<1; 7.1049 + break; 7.1050 + case 0xcd: 7.1051 + // SET 1,L 7.1052 + HL.B.B0|=1<<1; 7.1053 + break; 7.1054 + case 0xce: 7.1055 + // SET 1,(HL) 7.1056 + tempValue=gbReadMemory(HL.W); 7.1057 + tempValue|=1<<1; 7.1058 + gbWriteMemory(HL.W,tempValue); 7.1059 + break; 7.1060 + case 0xcf: 7.1061 + // SET 1,A 7.1062 + AF.B.B1|=1<<1; 7.1063 + break; 7.1064 + case 0xd0: 7.1065 + // SET 2,B 7.1066 + BC.B.B1|=1<<2; 7.1067 + break; 7.1068 + case 0xd1: 7.1069 + // SET 2,C 7.1070 + BC.B.B0|=1<<2; 7.1071 + break; 7.1072 + case 0xd2: 7.1073 + // SET 2,D 7.1074 + DE.B.B1|=1<<2; 7.1075 + break; 7.1076 + case 0xd3: 7.1077 + // SET 2,E 7.1078 + DE.B.B0|=1<<2; 7.1079 + break; 7.1080 + case 0xd4: 7.1081 + // SET 2,H 7.1082 + HL.B.B1|=1<<2; 7.1083 + break; 7.1084 + case 0xd5: 7.1085 + // SET 2,L 7.1086 + HL.B.B0|=1<<2; 7.1087 + break; 7.1088 + case 0xd6: 7.1089 + // SET 2,(HL) 7.1090 + tempValue=gbReadMemory(HL.W); 7.1091 + tempValue|=1<<2; 7.1092 + gbWriteMemory(HL.W,tempValue); 7.1093 + break; 7.1094 + case 0xd7: 7.1095 + // SET 2,A 7.1096 + AF.B.B1|=1<<2; 7.1097 + break; 7.1098 + case 0xd8: 7.1099 + // SET 3,B 7.1100 + BC.B.B1|=1<<3; 7.1101 + break; 7.1102 + case 0xd9: 7.1103 + // SET 3,C 7.1104 + BC.B.B0|=1<<3; 7.1105 + break; 7.1106 + case 0xda: 7.1107 + // SET 3,D 7.1108 + DE.B.B1|=1<<3; 7.1109 + break; 7.1110 + case 0xdb: 7.1111 + // SET 3,E 7.1112 + DE.B.B0|=1<<3; 7.1113 + break; 7.1114 + case 0xdc: 7.1115 + // SET 3,H 7.1116 + HL.B.B1|=1<<3; 7.1117 + break; 7.1118 + case 0xdd: 7.1119 + // SET 3,L 7.1120 + HL.B.B0|=1<<3; 7.1121 + break; 7.1122 + case 0xde: 7.1123 + // SET 3,(HL) 7.1124 + tempValue=gbReadMemory(HL.W); 7.1125 + tempValue|=1<<3; 7.1126 + gbWriteMemory(HL.W,tempValue); 7.1127 + break; 7.1128 + case 0xdf: 7.1129 + // SET 3,A 7.1130 + AF.B.B1|=1<<3; 7.1131 + break; 7.1132 + case 0xe0: 7.1133 + // SET 4,B 7.1134 + BC.B.B1|=1<<4; 7.1135 + break; 7.1136 + case 0xe1: 7.1137 + // SET 4,C 7.1138 + BC.B.B0|=1<<4; 7.1139 + break; 7.1140 + case 0xe2: 7.1141 + // SET 4,D 7.1142 + DE.B.B1|=1<<4; 7.1143 + break; 7.1144 + case 0xe3: 7.1145 + // SET 4,E 7.1146 + DE.B.B0|=1<<4; 7.1147 + break; 7.1148 + case 0xe4: 7.1149 + // SET 4,H 7.1150 + HL.B.B1|=1<<4; 7.1151 + break; 7.1152 + case 0xe5: 7.1153 + // SET 4,L 7.1154 + HL.B.B0|=1<<4; 7.1155 + break; 7.1156 + case 0xe6: 7.1157 + // SET 4,(HL) 7.1158 + tempValue=gbReadMemory(HL.W); 7.1159 + tempValue|=1<<4; 7.1160 + gbWriteMemory(HL.W,tempValue); 7.1161 + break; 7.1162 + case 0xe7: 7.1163 + // SET 4,A 7.1164 + AF.B.B1|=1<<4; 7.1165 + break; 7.1166 + case 0xe8: 7.1167 + // SET 5,B 7.1168 + BC.B.B1|=1<<5; 7.1169 + break; 7.1170 + case 0xe9: 7.1171 + // SET 5,C 7.1172 + BC.B.B0|=1<<5; 7.1173 + break; 7.1174 + case 0xea: 7.1175 + // SET 5,D 7.1176 + DE.B.B1|=1<<5; 7.1177 + break; 7.1178 + case 0xeb: 7.1179 + // SET 5,E 7.1180 + DE.B.B0|=1<<5; 7.1181 + break; 7.1182 + case 0xec: 7.1183 + // SET 5,H 7.1184 + HL.B.B1|=1<<5; 7.1185 + break; 7.1186 + case 0xed: 7.1187 + // SET 5,L 7.1188 + HL.B.B0|=1<<5; 7.1189 + break; 7.1190 + case 0xee: 7.1191 + // SET 5,(HL) 7.1192 + tempValue=gbReadMemory(HL.W); 7.1193 + tempValue|=1<<5; 7.1194 + gbWriteMemory(HL.W,tempValue); 7.1195 + break; 7.1196 + case 0xef: 7.1197 + // SET 5,A 7.1198 + AF.B.B1|=1<<5; 7.1199 + break; 7.1200 + case 0xf0: 7.1201 + // SET 6,B 7.1202 + BC.B.B1|=1<<6; 7.1203 + break; 7.1204 + case 0xf1: 7.1205 + // SET 6,C 7.1206 + BC.B.B0|=1<<6; 7.1207 + break; 7.1208 + case 0xf2: 7.1209 + // SET 6,D 7.1210 + DE.B.B1|=1<<6; 7.1211 + break; 7.1212 + case 0xf3: 7.1213 + // SET 6,E 7.1214 + DE.B.B0|=1<<6; 7.1215 + break; 7.1216 + case 0xf4: 7.1217 + // SET 6,H 7.1218 + HL.B.B1|=1<<6; 7.1219 + break; 7.1220 + case 0xf5: 7.1221 + // SET 6,L 7.1222 + HL.B.B0|=1<<6; 7.1223 + break; 7.1224 + case 0xf6: 7.1225 + // SET 6,(HL) 7.1226 + tempValue=gbReadMemory(HL.W); 7.1227 + tempValue|=1<<6; 7.1228 + gbWriteMemory(HL.W,tempValue); 7.1229 + break; 7.1230 + case 0xf7: 7.1231 + // SET 6,A 7.1232 + AF.B.B1|=1<<6; 7.1233 + break; 7.1234 + case 0xf8: 7.1235 + // SET 7,B 7.1236 + BC.B.B1|=1<<7; 7.1237 + break; 7.1238 + case 0xf9: 7.1239 + // SET 7,C 7.1240 + BC.B.B0|=1<<7; 7.1241 + break; 7.1242 + case 0xfa: 7.1243 + // SET 7,D 7.1244 + DE.B.B1|=1<<7; 7.1245 + break; 7.1246 + case 0xfb: 7.1247 + // SET 7,E 7.1248 + DE.B.B0|=1<<7; 7.1249 + break; 7.1250 + case 0xfc: 7.1251 + // SET 7,H 7.1252 + HL.B.B1|=1<<7; 7.1253 + break; 7.1254 + case 0xfd: 7.1255 + // SET 7,L 7.1256 + HL.B.B0|=1<<7; 7.1257 + break; 7.1258 + case 0xfe: 7.1259 + // SET 7,(HL) 7.1260 + tempValue=gbReadMemory(HL.W); 7.1261 + tempValue|=1<<7; 7.1262 + gbWriteMemory(HL.W,tempValue); 7.1263 + break; 7.1264 + case 0xff: 7.1265 + // SET 7,A 7.1266 + AF.B.B1|=1<<7; 7.1267 + break; 7.1268 + default: 7.1269 + systemMessage(0, N_("Unknown opcode %02x at %04x"), 7.1270 + gbReadOpcode(PC.W-1),PC.W-1); 7.1271 + emulating = false; 7.1272 + return;
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/src/gb/gbDis.cpp Sat Mar 03 11:44:47 2012 -0600 8.3 @@ -0,0 +1,239 @@ 8.4 +#include <cstdio> 8.5 +#include <cstring> 8.6 + 8.7 +#include "gbGlobals.h" 8.8 + 8.9 +typedef struct 8.10 +{ 8.11 + u8 mask; 8.12 + u8 value; 8.13 + char *mnen; 8.14 +} GBOPCODE; 8.15 + 8.16 +static char *registers[] = 8.17 +{ "B", "C", "D", "E", "H", "L", "(HL)", "A" }; 8.18 + 8.19 +static char *registers16[] = 8.20 +{ "BC", "DE", "HL", "SP", // for some operations 8.21 + "BC", "DE", "HL", "AF" }; // for push/pop 8.22 + 8.23 +static char *cond[] = 8.24 +{ "NZ", "Z", "NC", "C" }; 8.25 + 8.26 +static char hexDigits[16] = { 8.27 + '0', '1', '2', '3', '4', '5', '6', '7', 8.28 + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' 8.29 +}; 8.30 + 8.31 +static GBOPCODE opcodes[] = { 8.32 + { 0xff, 0x00, "NOP" }, 8.33 + { 0xcf, 0x01, "LD %R4,%W" }, 8.34 + { 0xff, 0x02, "LD (BC),A" }, 8.35 + { 0xcf, 0x03, "INC %R4" }, 8.36 + { 0xc7, 0x04, "INC %r3" }, 8.37 + { 0xc7, 0x05, "DEC %r3" }, 8.38 + { 0xc7, 0x06, "LD %r3,%B" }, 8.39 + { 0xff, 0x07, "RLCA" }, 8.40 + { 0xff, 0x08, "LD (%W),SP" }, 8.41 + { 0xcf, 0x09, "ADD HL,%R4" }, 8.42 + { 0xff, 0x0a, "LD A,(BC)" }, 8.43 + { 0xcf, 0x0b, "DEC %R4" }, 8.44 + { 0xff, 0x0f, "RRCA" }, 8.45 + { 0xff, 0x10, "STOP" }, 8.46 + { 0xff, 0x12, "LD (DE),A" }, 8.47 + { 0xff, 0x17, "RLA" }, 8.48 + { 0xff, 0x18, "JR %d" }, 8.49 + { 0xff, 0x1a, "LD A,(DE)" }, 8.50 + { 0xff, 0x1f, "RRA" }, 8.51 + { 0xe7, 0x20, "JR %c3,%d" }, 8.52 + { 0xff, 0x22, "LDI (HL),A" }, 8.53 + { 0xff, 0x27, "DAA" }, 8.54 + { 0xff, 0x2a, "LDI A,(HL)" }, 8.55 + { 0xff, 0x2f, "CPL" }, 8.56 + { 0xff, 0x32, "LDD (HL),A" }, 8.57 + { 0xff, 0x37, "SCF" }, 8.58 + { 0xff, 0x3a, "LDD A,(HL)" }, 8.59 + { 0xff, 0x3f, "CCF" }, 8.60 + { 0xff, 0x76, "HALT" }, 8.61 + { 0xc0, 0x40, "LD %r3,%r0" }, 8.62 + { 0xf8, 0x80, "ADD A,%r0" }, 8.63 + { 0xf8, 0x88, "ADC A,%r0" }, 8.64 + { 0xf8, 0x90, "SUB %r0" }, 8.65 + { 0xf8, 0x98, "SBC A,%r0" }, 8.66 + { 0xf8, 0xa0, "AND %r0" }, 8.67 + { 0xf8, 0xa8, "XOR %r0" }, 8.68 + { 0xf8, 0xb0, "OR %r0" }, 8.69 + { 0xf8, 0xb8, "CP %r0" }, 8.70 + { 0xe7, 0xc0, "RET %c3" }, 8.71 + { 0xcf, 0xc1, "POP %t4" }, 8.72 + { 0xe7, 0xc2, "JP %c3,%W" }, 8.73 + { 0xff, 0xc3, "JP %W" }, 8.74 + { 0xe7, 0xc4, "CALL %c3,%W" }, 8.75 + { 0xcf, 0xc5, "PUSH %t4" }, 8.76 + { 0xff, 0xc6, "ADD A,%B" }, 8.77 + { 0xc7, 0xc7, "RST %P" }, 8.78 + { 0xff, 0xc9, "RET" }, 8.79 + { 0xff, 0xcd, "CALL %W" }, 8.80 + { 0xff, 0xce, "ADC %B" }, 8.81 + { 0xff, 0xd6, "SUB %B" }, 8.82 + { 0xff, 0xd9, "RETI" }, 8.83 + { 0xff, 0xde, "SBC %B" }, 8.84 + { 0xff, 0xe0, "LD (FF%B),A" }, 8.85 + { 0xff, 0xe2, "LD (FF00h+C),A" }, 8.86 + { 0xff, 0xe6, "AND %B" }, 8.87 + { 0xff, 0xe8, "ADD SP,%D" }, 8.88 + { 0xff, 0xe9, "LD PC,HL" }, 8.89 + { 0xff, 0xea, "LD (%W),A" }, 8.90 + { 0xff, 0xee, "XOR %B" }, 8.91 + { 0xff, 0xf0, "LD A,(FF%B)" }, 8.92 + { 0xff, 0xf2, "LD A,(FF00h+C)" }, 8.93 + { 0xff, 0xf3, "DI" }, 8.94 + { 0xff, 0xf6, "OR %B" }, 8.95 + { 0xff, 0xf8, "LD HL,SP%D" }, 8.96 + { 0xff, 0xf9, "LD SP,HL" }, 8.97 + { 0xff, 0xfa, "LD A,(%W)" }, 8.98 + { 0xff, 0xfb, "EI" }, 8.99 + { 0xff, 0xfe, "CP %B" }, 8.100 + { 0x00, 0x00, "DB %B" } 8.101 +}; 8.102 + 8.103 +static GBOPCODE cbOpcodes[] = { 8.104 + { 0xf8, 0x00, "RLC %r0" }, 8.105 + { 0xf8, 0x08, "RRC %r0" }, 8.106 + { 0xf8, 0x10, "RL %r0" }, 8.107 + { 0xf8, 0x18, "RR %r0" }, 8.108 + { 0xf8, 0x20, "SLA %r0" }, 8.109 + { 0xf8, 0x28, "SRA %r0" }, 8.110 + { 0xf8, 0x30, "SWAP %r0" }, 8.111 + { 0xf8, 0x38, "SRL %r0" }, 8.112 + { 0xc0, 0x40, "BIT %b,%r0" }, 8.113 + { 0xc0, 0x80, "RES %b,%r0" }, 8.114 + { 0xc0, 0xc0, "SET %b,%r0" }, 8.115 + { 0x00, 0x00, "DB CBh,%B" } 8.116 +}; 8.117 + 8.118 +static char *addHex(char *p, u8 value) 8.119 +{ 8.120 + *p++ = hexDigits[value >> 4]; 8.121 + *p++ = hexDigits[value & 15]; 8.122 + return p; 8.123 +} 8.124 + 8.125 +static char *addHex16(char *p, u16 value) 8.126 +{ 8.127 + p = addHex(p, value>>8); 8.128 + return addHex(p, value & 255); 8.129 +} 8.130 + 8.131 +static char *addStr(char *p, char *s) 8.132 +{ 8.133 + while (*s) 8.134 + { 8.135 + *p++ = *s++; 8.136 + } 8.137 + return p; 8.138 +} 8.139 + 8.140 +int gbDis(char *buffer, u16 address) 8.141 +{ 8.142 + char *p = buffer; 8.143 + int instr = 1; 8.144 + u16 addr = address; 8.145 + sprintf(p, "%04x ", address); 8.146 + p += 12; 8.147 + 8.148 + u8 opcode = gbReadMemoryQuick(address); 8.149 + address++; 8.150 + char * mnen; 8.151 + GBOPCODE *op; 8.152 + if (opcode == 0xcb) 8.153 + { 8.154 + opcode = gbReadMemoryQuick(address); 8.155 + address++; 8.156 + instr++; 8.157 + op = cbOpcodes; 8.158 + } 8.159 + else 8.160 + { 8.161 + op = opcodes; 8.162 + } 8.163 + while (op->value != (opcode & op->mask)) 8.164 + op++; 8.165 + mnen = op->mnen; 8.166 + 8.167 + u8 b0, b1; 8.168 + s8 disp; 8.169 + int shift; 8.170 + 8.171 + while (*mnen) 8.172 + { 8.173 + if (*mnen == '%') 8.174 + { 8.175 + mnen++; 8.176 + switch (*mnen++) 8.177 + { 8.178 + case 'W': 8.179 + b0 = gbReadMemoryQuick(address); 8.180 + address++; 8.181 + b1 = gbReadMemoryQuick(address); 8.182 + address++; 8.183 + p = addHex16(p, b0|b1<<8); 8.184 + instr += 2; 8.185 + *p++ = 'h'; 8.186 + break; 8.187 + case 'B': 8.188 + p = addHex(p, gbReadMemoryQuick(address)); 8.189 + *p++ = 'h'; 8.190 + address++; 8.191 + instr++; 8.192 + break; 8.193 + case 'D': 8.194 + disp = gbReadMemoryQuick(address); 8.195 + if (disp >= 0) 8.196 + *p++ = '+'; 8.197 + p += sprintf(p, "%d", disp); 8.198 + instr++; 8.199 + break; 8.200 + case 'd': 8.201 + disp = gbReadMemoryQuick(address); 8.202 + address++; 8.203 + p = addHex16(p, address+disp); 8.204 + *p++ = 'h'; 8.205 + instr++; 8.206 + break; 8.207 + case 'b': 8.208 + // kind of a hack, but it works :-) 8.209 + *p++ = hexDigits[(opcode >> 3) & 7]; 8.210 + break; 8.211 + case 'r': 8.212 + shift = *mnen++ - '0'; 8.213 + p = addStr(p, registers[(opcode >> shift) & 7]); 8.214 + break; 8.215 + case 'R': 8.216 + shift = *mnen++ - '0'; 8.217 + p = addStr(p, registers16[(opcode >> shift) & 3]); 8.218 + break; 8.219 + case 't': 8.220 + shift = *mnen++ - '0'; 8.221 + p = addStr(p, registers16[4+((opcode >> shift) & 3)]); 8.222 + break; 8.223 + case 'P': 8.224 + p = addHex(p, ((opcode >> 3) & 7) * 8); 8.225 + break; 8.226 + case 'c': 8.227 + shift = *mnen++ - '0'; 8.228 + p = addStr(p, cond[(opcode >> shift) & 3]); 8.229 + break; 8.230 + } 8.231 + } 8.232 + else 8.233 + *p++ = *mnen++; 8.234 + } 8.235 + for (int i = 0; i < instr; i++) 8.236 + { 8.237 + u16 a = addr + i; 8.238 + addHex(buffer+5+i*2, gbReadMemoryQuick(a)); 8.239 + } 8.240 + *p = 0; 8.241 + return instr; 8.242 +}
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 9.2 +++ b/src/gb/gbGfx.cpp Sat Mar 03 11:44:47 2012 -0600 9.3 @@ -0,0 +1,552 @@ 9.4 +#include <cstring> 9.5 + 9.6 +#include "gbGlobals.h" 9.7 +#include "gbSGB.h" 9.8 + 9.9 +extern int32 layerSettings; 9.10 + 9.11 +u8 gbInvertTab[256] = { 9.12 + 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 9.13 + 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, 9.14 + 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 9.15 + 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, 9.16 + 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 9.17 + 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, 9.18 + 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 9.19 + 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, 9.20 + 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 9.21 + 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, 9.22 + 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, 9.23 + 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, 9.24 + 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 9.25 + 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, 9.26 + 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 9.27 + 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, 9.28 + 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, 9.29 + 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, 9.30 + 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 9.31 + 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, 9.32 + 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, 9.33 + 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, 9.34 + 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 9.35 + 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, 9.36 + 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 9.37 + 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, 9.38 + 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 9.39 + 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, 9.40 + 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, 9.41 + 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, 9.42 + 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 9.43 + 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff 9.44 +}; 9.45 + 9.46 +u16 gbLineMix[160]; 9.47 + 9.48 +void gbRenderLine() 9.49 +{ 9.50 + u8 *bank0; 9.51 + u8 *bank1; 9.52 + if (gbCgbMode) 9.53 + { 9.54 + bank0 = &gbVram[0x0000]; 9.55 + bank1 = &gbVram[0x2000]; 9.56 + } 9.57 + else 9.58 + { 9.59 + bank0 = &gbMemory[0x8000]; 9.60 + bank1 = NULL; 9.61 + } 9.62 + 9.63 + int tile_map = 0x1800; 9.64 + if ((register_LCDC & 8) != 0) 9.65 + tile_map = 0x1c00; 9.66 + 9.67 + int tile_pattern = 0x0800; 9.68 + 9.69 + if ((register_LCDC & 16) != 0) 9.70 + tile_pattern = 0x0000; 9.71 + 9.72 + int x = 0; 9.73 + int y = register_LY; 9.74 + 9.75 + if (y >= 144) 9.76 + return; 9.77 + 9.78 + // int yLine = (y + gbBorderRowSkip) * gbBorderLineSkip; 9.79 + 9.80 + int sx = register_SCX; 9.81 + int sy = register_SCY; 9.82 + 9.83 + sy += y; 9.84 + 9.85 + sy &= 255; 9.86 + 9.87 + int tx = sx >> 3; 9.88 + int ty = sy >> 3; 9.89 + 9.90 + int bx = 1 << (7 - (sx & 7)); 9.91 + int by = sy & 7; 9.92 + 9.93 + int tile_map_line_y = tile_map + ty * 32; 9.94 + 9.95 + int tile_map_address = tile_map_line_y + tx; 9.96 + 9.97 + u8 attrs = 0; 9.98 + if (bank1 != NULL) 9.99 + attrs = bank1[tile_map_address]; 9.100 + 9.101 + u8 tile = bank0[tile_map_address]; 9.102 + 9.103 + tile_map_address++; 9.104 + 9.105 + if ((register_LCDC & 16) == 0) 9.106 + { 9.107 + if (tile < 128) 9.108 + tile += 128; 9.109 + else 9.110 + tile -= 128; 9.111 + } 9.112 + 9.113 + int tile_pattern_address = tile_pattern + tile * 16 + by*2; 9.114 + 9.115 + if (register_LCDC & 0x80) 9.116 + { 9.117 + if ((register_LCDC & 0x01 || gbCgbMode) && (layerSettings & 0x0100)) 9.118 + { 9.119 + while (x < 160) 9.120 + { 9.121 + u8 tile_a = 0; 9.122 + u8 tile_b = 0; 9.123 + 9.124 + if (attrs & 0x40) 9.125 + { 9.126 + tile_pattern_address = tile_pattern + tile * 16 + (7-by)*2; 9.127 + } 9.128 + 9.129 + if (attrs & 0x08) 9.130 + { 9.131 + tile_a = bank1[tile_pattern_address++]; 9.132 + tile_b = bank1[tile_pattern_address]; 9.133 + } 9.134 + else 9.135 + { 9.136 + tile_a = bank0[tile_pattern_address++]; 9.137 + tile_b = bank0[tile_pattern_address]; 9.138 + } 9.139 + 9.140 + if (attrs & 0x20) 9.141 + { 9.142 + tile_a = gbInvertTab[tile_a]; 9.143 + tile_b = gbInvertTab[tile_b]; 9.144 + } 9.145 + 9.146 + while (bx > 0) 9.147 + { 9.148 + u8 c = (tile_a & bx) ? 1 : 0; 9.149 + c += ((tile_b & bx) ? 2 : 0); 9.150 + 9.151 + gbLineBuffer[x] = c; // mark the gbLineBuffer color 9.152 + 9.153 + if (attrs & 0x80) 9.154 + gbLineBuffer[x] |= 0x300; 9.155 + 9.156 + if (gbCgbMode) 9.157 + { 9.158 + c = c + (attrs & 7)*4; 9.159 + } 9.160 + else 9.161 + { 9.162 + c = gbBgp[c]; 9.163 + if (gbSgbMode && !gbCgbMode) 9.164 + { 9.165 + int dx = x >> 3; 9.166 + int dy = y >> 3; 9.167 + 9.168 + int palette = gbSgbATF[dy * 20 + dx]; 9.169 + 9.170 + if (c == 0) 9.171 + palette = 0; 9.172 + 9.173 + c = c + 4*palette; 9.174 + } 9.175 + } 9.176 + gbLineMix[x] = gbColorOption ? gbColorFilter[gbPalette[c]] : 9.177 + gbPalette[c]; 9.178 + x++; 9.179 + if (x >= 160) 9.180 + break; 9.181 + bx >>= 1; 9.182 + } 9.183 + tx++; 9.184 + if (tx == 32) 9.185 + tx = 0; 9.186 + bx = 128; 9.187 + 9.188 + if (bank1) 9.189 + attrs = bank1[tile_map_line_y + tx]; 9.190 + 9.191 + tile = bank0[tile_map_line_y + tx]; 9.192 + 9.193 + if ((register_LCDC & 16) == 0) 9.194 + { 9.195 + if (tile < 128) 9.196 + tile += 128; 9.197 + else 9.198 + tile -= 128; 9.199 + } 9.200 + tile_pattern_address = tile_pattern + tile * 16 + by * 2; 9.201 + } 9.202 + } 9.203 + else 9.204 + { 9.205 + for (int i = 0; i < 160; i++) 9.206 + { 9.207 + gbLineMix[i] = gbPalette[0]; 9.208 + gbLineBuffer[i] = 0; 9.209 + } 9.210 + } 9.211 + 9.212 + // do the window display 9.213 + if ((register_LCDC & 0x20) && (layerSettings & 0x2000)) 9.214 + { 9.215 + int wy = register_WY; 9.216 + 9.217 + if (y >= wy) 9.218 + { 9.219 + int wx = register_WX; 9.220 + wx -= 7; 9.221 + 9.222 + if (wx <= 159 && gbWindowLine <= 143) 9.223 + { 9.224 + tile_map = 0x1800; 9.225 + 9.226 + if ((register_LCDC & 0x40) != 0) 9.227 + tile_map = 0x1c00; 9.228 + 9.229 + if (gbWindowLine == -1) 9.230 + { 9.231 + gbWindowLine = 0; 9.232 + } 9.233 + 9.234 + tx = 0; 9.235 + ty = gbWindowLine >> 3; 9.236 + 9.237 + bx = 128; 9.238 + by = gbWindowLine & 7; 9.239 + 9.240 + if (wx < 0) 9.241 + { 9.242 + bx >>= (-wx); 9.243 + wx = 0; 9.244 + } 9.245 + 9.246 + tile_map_line_y = tile_map + ty * 32; 9.247 + 9.248 + tile_map_address = tile_map_line_y + tx; 9.249 + 9.250 + x = wx; 9.251 + 9.252 + tile = bank0[tile_map_address]; 9.253 + u8 attrs = 0; 9.254 + if (bank1) 9.255 + attrs = bank1[tile_map_address]; 9.256 + tile_map_address++; 9.257 + 9.258 + if ((register_LCDC & 16) == 0) 9.259 + { 9.260 + if (tile < 128) 9.261 + tile += 128; 9.262 + else 9.263 + tile -= 128; 9.264 + } 9.265 + 9.266 + tile_pattern_address = tile_pattern + tile * 16 + by*2; 9.267 + 9.268 + while (x < 160) 9.269 + { 9.270 + u8 tile_a = 0; 9.271 + u8 tile_b = 0; 9.272 + 9.273 + if (attrs & 0x40) 9.274 + { 9.275 + tile_pattern_address = tile_pattern + tile * 16 + (7-by)*2; 9.276 + } 9.277 + 9.278 + if (attrs & 0x08) 9.279 + { 9.280 + tile_a = bank1[tile_pattern_address++]; 9.281 + tile_b = bank1[tile_pattern_address]; 9.282 + } 9.283 + else 9.284 + { 9.285 + tile_a = bank0[tile_pattern_address++]; 9.286 + tile_b = bank0[tile_pattern_address]; 9.287 + } 9.288 + 9.289 + if (attrs & 0x20) 9.290 + { 9.291 + tile_a = gbInvertTab[tile_a]; 9.292 + tile_b = gbInvertTab[tile_b]; 9.293 + } 9.294 + 9.295 + while (bx > 0) 9.296 + { 9.297 + u8 c = (tile_a & bx) != 0 ? 1 : 0; 9.298 + c += ((tile_b & bx) != 0 ? 2 : 0); 9.299 + 9.300 + if (attrs & 0x80) 9.301 + gbLineBuffer[x] = 0x300 + c; 9.302 + else 9.303 + gbLineBuffer[x] = 0x100 + c; 9.304 + 9.305 + if (gbCgbMode) 9.306 + { 9.307 + c = c + (attrs & 7) * 4; 9.308 + } 9.309 + else 9.310 + { 9.311 + c = gbBgp[c]; 9.312 + if (gbSgbMode && !gbCgbMode) 9.313 + { 9.314 + int dx = x >> 3; 9.315 + int dy = y >> 3; 9.316 + 9.317 + int palette = gbSgbATF[dy * 20 + dx]; 9.318 + 9.319 + if (c == 0) 9.320 + palette = 0; 9.321 + 9.322 + c = c + 4*palette; 9.323 + } 9.324 + } 9.325 + gbLineMix[x] = gbColorOption ? gbColorFilter[gbPalette[c]] : 9.326 + gbPalette[c]; 9.327 + x++; 9.328 + if (x >= 160) 9.329 + break; 9.330 + bx >>= 1; 9.331 + } 9.332 + tx++; 9.333 + if (tx == 32) 9.334 + tx = 0; 9.335 + bx = 128; 9.336 + tile = bank0[tile_map_line_y + tx]; 9.337 + if (bank1) 9.338 + attrs = bank1[tile_map_line_y + tx]; 9.339 + 9.340 + if ((register_LCDC & 16) == 0) 9.341 + { 9.342 + if (tile < 128) 9.343 + tile += 128; 9.344 + else 9.345 + tile -= 128; 9.346 + } 9.347 + tile_pattern_address = tile_pattern + tile * 16 + by * 2; 9.348 + } 9.349 + gbWindowLine++; 9.350 + } 9.351 + } 9.352 + } 9.353 + } 9.354 + else 9.355 + { 9.356 + for (int i = 0; i < 160; i++) 9.357 + { 9.358 + gbLineMix[i] = gbPalette[0]; 9.359 + gbLineBuffer[i] = 0; 9.360 + } 9.361 + } 9.362 +} 9.363 + 9.364 +void gbDrawSpriteTile(int tile, int x, int y, int t, int flags, 9.365 + int size, int spriteNumber) 9.366 +{ 9.367 + u8 *bank0; 9.368 + u8 *bank1; 9.369 + if (gbCgbMode) 9.370 + { 9.371 + if (register_VBK & 1) 9.372 + { 9.373 + bank0 = &gbVram[0x0000]; 9.374 + bank1 = &gbVram[0x2000]; 9.375 + } 9.376 + else 9.377 + { 9.378 + bank0 = &gbVram[0x0000]; 9.379 + bank1 = &gbVram[0x2000]; 9.380 + } 9.381 + } 9.382 + else 9.383 + { 9.384 + bank0 = &gbMemory[0x8000]; 9.385 + bank1 = NULL; 9.386 + } 9.387 + 9.388 + int init = 0x0000; 9.389 + 9.390 + // int yLine = (y+gbBorderRowSkip) * gbBorderLineSkip; 9.391 + 9.392 + u8 *pal = gbObp0; 9.393 + 9.394 + int flipx = (flags & 0x20); 9.395 + int flipy = (flags & 0x40); 9.396 + 9.397 + if ((flags & 0x10)) 9.398 + pal = gbObp1; 9.399 + 9.400 + if (flipy) 9.401 + { 9.402 + t = (size ? 15 : 7) - t; 9.403 + } 9.404 + 9.405 + int prio = flags & 0x80; 9.406 + 9.407 + int address = init + tile * 16 + 2*t; 9.408 + int a = 0; 9.409 + int b = 0; 9.410 + 9.411 + if (gbCgbMode && flags & 0x08) 9.412 + { 9.413 + a = bank1[address++]; 9.414 + b = bank1[address++]; 9.415 + } 9.416 + else 9.417 + { 9.418 + a = bank0[address++]; 9.419 + b = bank0[address++]; 9.420 + } 9.421 + 9.422 + for (int xx = 0; xx < 8; xx++) 9.423 + { 9.424 + u8 mask = 1 << (7-xx); 9.425 + u8 c = 0; 9.426 + if ((a & mask)) 9.427 + c++; 9.428 + if ((b & mask)) 9.429 + c += 2; 9.430 + 9.431 + if (c == 0) 9.432 + continue; 9.433 + 9.434 + int xxx = xx+x; 9.435 + if (flipx) 9.436 + xxx = (7-xx+x); 9.437 + 9.438 + if (xxx < 0 || xxx > 159) 9.439 + continue; 9.440 + 9.441 + u16 color = gbLineBuffer[xxx]; 9.442 + 9.443 + if (prio) 9.444 + { 9.445 + if (color < 0x200 && ((color & 0xFF) != 0)) 9.446 + continue; 9.447 + } 9.448 + if (color >= 0x300 && color != 0x300) 9.449 + continue; 9.450 + else if (color >= 0x200 && color < 0x300) 9.451 + { 9.452 + int sprite = color & 0xff; 9.453 + 9.454 + int spriteX = gbMemory[0xfe00 + 4 * sprite + 1] - 8; 9.455 + 9.456 + if (spriteX == x) 9.457 + { 9.458 + if (sprite < spriteNumber) 9.459 + continue; 9.460 + } 9.461 + else 9.462 + { 9.463 + if (gbCgbMode) 9.464 + { 9.465 + if (sprite < spriteNumber) 9.466 + continue; 9.467 + } 9.468 + else 9.469 + { 9.470 + if (spriteX < x+8) 9.471 + continue; 9.472 + } 9.473 + } 9.474 + } 9.475 + 9.476 + gbLineBuffer[xxx] = 0x200 + spriteNumber; 9.477 + 9.478 + // make sure that sprites will work even in CGB mode 9.479 + if (gbCgbMode) 9.480 + { 9.481 + c = c + (flags & 0x07)*4 + 32; 9.482 + } 9.483 + else 9.484 + { 9.485 + c = pal[c]; 9.486 + 9.487 + if (gbSgbMode && !gbCgbMode) 9.488 + { 9.489 + int dx = xxx >> 3; 9.490 + int dy = y >> 3; 9.491 + 9.492 + int palette = gbSgbATF[dy * 20 + dx]; 9.493 + 9.494 + if (c == 0) 9.495 + palette = 0; 9.496 + 9.497 + c = c + 4*palette; 9.498 + } 9.499 + else 9.500 + { 9.501 + c += 4; 9.502 + } 9.503 + } 9.504 + 9.505 + gbLineMix[xxx] = gbColorOption ? gbColorFilter[gbPalette[c]] : 9.506 + gbPalette[c]; 9.507 + } 9.508 +} 9.509 + 9.510 +void gbDrawSprites() 9.511 +{ 9.512 + int x = 0; 9.513 + int y = 0; 9.514 + int count = 0; 9.515 + 9.516 + int size = (register_LCDC & 4); 9.517 + 9.518 + if (!(register_LCDC & 0x80)) 9.519 + return; 9.520 + 9.521 + if ((register_LCDC & 2) && (layerSettings & 0x1000)) 9.522 + { 9.523 + int yc = register_LY; 9.524 + 9.525 + int address = 0xfe00; 9.526 + for (int i = 0; i < 40; i++) 9.527 + { 9.528 + y = gbMemory[address++]; 9.529 + x = gbMemory[address++]; 9.530 + int tile = gbMemory[address++]; 9.531 + if (size) 9.532 + tile &= 254; 9.533 + int flags = gbMemory[address++]; 9.534 + 9.535 + if (x > 0 && y > 0 && x < 168 && y < 160) 9.536 + { 9.537 + // check if sprite intersects current line 9.538 + int t = yc -y + 16; 9.539 + if (size && t >= 0 && t < 16) 9.540 + { 9.541 + gbDrawSpriteTile(tile, x-8, yc, t, flags, size, i); 9.542 + count++; 9.543 + } 9.544 + else if (!size && t >= 0 && t < 8) 9.545 + { 9.546 + gbDrawSpriteTile(tile, x-8, yc, t, flags, size, i); 9.547 + count++; 9.548 + } 9.549 + } 9.550 + // sprite limit reached! 9.551 + if (count >= 10) 9.552 + break; 9.553 + } 9.554 + } 9.555 +}
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 10.2 +++ b/src/gb/gbGlobals.cpp Sat Mar 03 11:44:47 2012 -0600 10.3 @@ -0,0 +1,39 @@ 10.4 +#include "../Port.h" 10.5 +#include "GB.h" 10.6 + 10.7 +u8 *gbMemoryMap[16]; 10.8 + 10.9 +int32 gbRomSizeMask = 0; 10.10 +int32 gbRomSize = 0; 10.11 +int32 gbRamSizeMask = 0; 10.12 +int32 gbRamSize = 0; 10.13 + 10.14 +u8 * gbMemory = NULL; 10.15 +u8 * gbVram = NULL; 10.16 +u8 * gbRom = NULL; 10.17 +u8 * gbRam = NULL; 10.18 +u8 * gbWram = NULL; 10.19 +u16 *gbLineBuffer = NULL; 10.20 + 10.21 +u16 gbPalette[128]; 10.22 +u8 gbBgp[4] = { 0, 1, 2, 3}; 10.23 +u8 gbObp0[4] = { 0, 1, 2, 3}; 10.24 +u8 gbObp1[4] = { 0, 1, 2, 3}; 10.25 +int32 gbWindowLine = -1; 10.26 + 10.27 +int32 gbCgbMode = 0; 10.28 + 10.29 +u16 gbColorFilter[32768]; 10.30 +int32 gbColorOption = 0; 10.31 +int32 gbPaletteOption = 0; 10.32 +int32 gbEmulatorType = 0; 10.33 +int32 gbBorderOn = 1; 10.34 +int32 gbBorderAutomatic = 0; 10.35 +int32 gbBorderLineSkip = 160; 10.36 +int32 gbBorderRowSkip = 0; 10.37 +int32 gbBorderColumnSkip = 0; 10.38 +int32 gbDmaTicks = 0; 10.39 +bool8 gbNullInputHackEnabled = false; 10.40 +bool8 gbNullInputHackTempEnabled = false; 10.41 + 10.42 +u8 (*gbSerialFunction)(u8) = NULL;
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 11.2 +++ b/src/gb/gbGlobals.h Sat Mar 03 11:44:47 2012 -0600 11.3 @@ -0,0 +1,95 @@ 11.4 +#ifndef VBA_GB_GLOBALS_H 11.5 +#define VBA_GB_GLOBALS_H 11.6 + 11.7 +#if _MSC_VER > 1000 11.8 +#pragma once 11.9 +#endif // _MSC_VER > 1000 11.10 + 11.11 +#include "../Port.h" 11.12 + 11.13 +extern int32 gbRomSizeMask; 11.14 +extern int32 gbRomSize; 11.15 +extern int32 gbRamSize; 11.16 +extern int32 gbRamSizeMask; 11.17 + 11.18 +extern u8 * gbRom; 11.19 +extern u8 * gbRam; 11.20 +extern u8 * gbVram; 11.21 +extern u8 * gbWram; 11.22 +extern u8 * gbMemory; 11.23 +extern u16 *gbLineBuffer; 11.24 + 11.25 +extern u8 *gbMemoryMap[16]; 11.26 + 11.27 +inline u8 gbReadMemoryQuick(u16 address) 11.28 +{ 11.29 + extern int32 gbEchoRAMFixOn; 11.30 + if (gbEchoRAMFixOn) 11.31 + { 11.32 + if (address >= 0xe000 && address < 0xfe00) 11.33 + { 11.34 + address -= 0x2000; 11.35 + } 11.36 + } 11.37 + return gbMemoryMap[address>>12][address&0xfff]; 11.38 +} 11.39 + 11.40 +inline void gbWriteMemoryQuick(u16 address, u8 value) 11.41 +{ 11.42 + extern int32 gbEchoRAMFixOn; 11.43 + if (gbEchoRAMFixOn) 11.44 + { 11.45 + if (address >= 0xe000 && address < 0xfe00) 11.46 + { 11.47 + address -= 0x2000; 11.48 + } 11.49 + } 11.50 + gbMemoryMap[address>>12][address&0xfff] = value; 11.51 +} 11.52 + 11.53 +inline u8 gbReadROMQuick(u32 address) 11.54 +{ 11.55 + return gbRom[address]; 11.56 +} 11.57 + 11.58 +extern int32 gbFrameSkip; 11.59 +extern u16 gbColorFilter[32768]; 11.60 +extern int32 gbColorOption; 11.61 +extern int32 gbPaletteOption; 11.62 +extern int32 gbEmulatorType; 11.63 +extern int32 gbBorderOn; 11.64 +extern int32 gbBorderAutomatic; 11.65 +extern int32 gbCgbMode; 11.66 +extern int32 gbSgbMode; 11.67 +extern int32 gbWindowLine; 11.68 +extern int32 gbSpeed; 11.69 +extern u8 gbBgp[4]; 11.70 +extern u8 gbObp0[4]; 11.71 +extern u8 gbObp1[4]; 11.72 +extern u16 gbPalette[128]; 11.73 + 11.74 +extern u8 register_LCDC; 11.75 +extern u8 register_LY; 11.76 +extern u8 register_SCY; 11.77 +extern u8 register_SCX; 11.78 +extern u8 register_WY; 11.79 +extern u8 register_WX; 11.80 +extern u8 register_VBK; 11.81 + 11.82 +extern int emulating; 11.83 + 11.84 +extern int32 gbBorderLineSkip; 11.85 +extern int32 gbBorderRowSkip; 11.86 +extern int32 gbBorderColumnSkip; 11.87 +extern int32 gbDmaTicks; 11.88 + 11.89 +extern bool8 useOldFrameTiming; 11.90 +extern bool8 gbNullInputHackEnabled; 11.91 +extern bool8 gbNullInputHackTempEnabled; 11.92 + 11.93 +extern void gbRenderLine(); 11.94 +extern void gbDrawSprites(); 11.95 + 11.96 +extern u8 (*gbSerialFunction)(u8); 11.97 + 11.98 +#endif // VBA_GB_GLOBALS_H
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 12.2 +++ b/src/gb/gbMemory.cpp Sat Mar 03 11:44:47 2012 -0600 12.3 @@ -0,0 +1,1070 @@ 12.4 +#include "gbGlobals.h" 12.5 +#include "gbMemory.h" 12.6 +#include "../common/System.h" 12.7 +#include "../common/movie.h" 12.8 + 12.9 +mapperMBC1 gbDataMBC1 = { 12.10 + 0, // RAM enable 12.11 + 1, // ROM bank 12.12 + 0, // RAM bank 12.13 + 0, // memory model 12.14 + 0, // ROM high address 12.15 + 0 // RAM address 12.16 +}; 12.17 + 12.18 +// MBC1 ROM write registers 12.19 +void mapperMBC1ROM(u16 address, u8 value) 12.20 +{ 12.21 + int tmpAddress = 0; 12.22 + 12.23 + switch (address & 0x6000) 12.24 + { 12.25 + case 0x0000: // RAM enable register 12.26 + gbDataMBC1.mapperRAMEnable = ((value & 0x0a) == 0x0a ? 1 : 0); 12.27 + break; 12.28 + case 0x2000: // ROM bank select 12.29 + // value = value & 0x1f; 12.30 + if (value == 0) 12.31 + value = 1; 12.32 + if (value == gbDataMBC1.mapperROMBank) 12.33 + break; 12.34 + 12.35 + tmpAddress = value << 14; 12.36 + 12.37 + // check current model 12.38 + if (gbDataMBC1.mapperMemoryModel == 0) 12.39 + { 12.40 + // model is 16/8, so we have a high address in use 12.41 + tmpAddress |= (gbDataMBC1.mapperROMHighAddress) << 19; 12.42 + } 12.43 + 12.44 + tmpAddress &= gbRomSizeMask; 12.45 + gbDataMBC1.mapperROMBank = value; 12.46 + gbMemoryMap[0x04] = &gbRom[tmpAddress]; 12.47 + gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; 12.48 + gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; 12.49 + gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; 12.50 + break; 12.51 + case 0x4000: // RAM bank select 12.52 + if (gbDataMBC1.mapperMemoryModel == 1) 12.53 + { 12.54 + // 4/32 model, RAM bank switching provided 12.55 + value = value & 0x03; 12.56 + if (value == gbDataMBC1.mapperRAMBank) 12.57 + break; 12.58 + tmpAddress = value << 13; 12.59 + tmpAddress &= gbRamSizeMask; 12.60 + gbMemoryMap[0x0a] = &gbRam[tmpAddress]; 12.61 + gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000]; 12.62 + gbDataMBC1.mapperRAMBank = value; 12.63 + gbDataMBC1.mapperRAMAddress = tmpAddress; 12.64 + } 12.65 + else 12.66 + { 12.67 + // 16/8, set the high address 12.68 + gbDataMBC1.mapperROMHighAddress = value & 0x03; 12.69 + tmpAddress = gbDataMBC1.mapperROMBank << 14; 12.70 + tmpAddress |= (gbDataMBC1.mapperROMHighAddress) << 19; 12.71 + tmpAddress &= gbRomSizeMask; 12.72 + gbMemoryMap[0x04] = &gbRom[tmpAddress]; 12.73 + gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; 12.74 + gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; 12.75 + gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; 12.76 + } 12.77 + break; 12.78 + case 0x6000: // memory model select 12.79 + gbDataMBC1.mapperMemoryModel = value & 1; 12.80 + break; 12.81 + } 12.82 +} 12.83 + 12.84 +// MBC1 RAM write 12.85 +void mapperMBC1RAM(u16 address, u8 value) 12.86 +{ 12.87 + if (gbDataMBC1.mapperRAMEnable) 12.88 + { 12.89 + if (gbRamSize) 12.90 + { 12.91 + gbWriteMemoryQuick(address, value); 12.92 + systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED; 12.93 + } 12.94 + } 12.95 +} 12.96 + 12.97 +void memoryUpdateMapMBC1() 12.98 +{ 12.99 + int tmpAddress = gbDataMBC1.mapperROMBank << 14; 12.100 + 12.101 + // check current model 12.102 + if (gbDataMBC1.mapperMemoryModel == 1) 12.103 + { 12.104 + // model is 16/8, so we have a high address in use 12.105 + tmpAddress |= (gbDataMBC1.mapperROMHighAddress) << 19; 12.106 + } 12.107 + 12.108 + tmpAddress &= gbRomSizeMask; 12.109 + gbMemoryMap[0x04] = &gbRom[tmpAddress]; 12.110 + gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; 12.111 + gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; 12.112 + gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; 12.113 + 12.114 + if (gbRamSize) 12.115 + { 12.116 + gbMemoryMap[0x0a] = &gbRam[gbDataMBC1.mapperRAMAddress]; 12.117 + gbMemoryMap[0x0b] = &gbRam[gbDataMBC1.mapperRAMAddress + 0x1000]; 12.118 + } 12.119 +} 12.120 + 12.121 +mapperMBC2 gbDataMBC2 = { 12.122 + 0, // RAM enable 12.123 + 1 // ROM bank 12.124 +}; 12.125 + 12.126 +// MBC2 ROM write registers 12.127 +void mapperMBC2ROM(u16 address, u8 value) 12.128 +{ 12.129 + switch (address & 0x6000) 12.130 + { 12.131 + case 0x0000: // RAM enable 12.132 + if (!(address & 0x0100)) 12.133 + { 12.134 + gbDataMBC2.mapperRAMEnable = (value & 0x0f) == 0x0a; 12.135 + } 12.136 + break; 12.137 + case 0x2000: // ROM bank select 12.138 + if (address & 0x0100) 12.139 + { 12.140 + value &= 0x0f; 12.141 + 12.142 + if (value == 0) 12.143 + value = 1; 12.144 + if (gbDataMBC2.mapperROMBank != value) 12.145 + { 12.146 + gbDataMBC2.mapperROMBank = value; 12.147 + 12.148 + int tmpAddress = value << 14; 12.149 + 12.150 + tmpAddress &= gbRomSizeMask; 12.151 + 12.152 + gbMemoryMap[0x04] = &gbRom[tmpAddress]; 12.153 + gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; 12.154 + gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; 12.155 + gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; 12.156 + } 12.157 + } 12.158 + break; 12.159 + } 12.160 +} 12.161 + 12.162 +// MBC2 RAM write 12.163 +void mapperMBC2RAM(u16 address, u8 value) 12.164 +{ 12.165 + if (gbDataMBC2.mapperRAMEnable) 12.166 + { 12.167 + if (gbRamSize && address < 0xa200) 12.168 + { 12.169 + gbWriteMemoryQuick(address, value); 12.170 + systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED; 12.171 + } 12.172 + } 12.173 +} 12.174 + 12.175 +void memoryUpdateMapMBC2() 12.176 +{ 12.177 + int tmpAddress = gbDataMBC2.mapperROMBank << 14; 12.178 + 12.179 + tmpAddress &= gbRomSizeMask; 12.180 + 12.181 + gbMemoryMap[0x04] = &gbRom[tmpAddress]; 12.182 + gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; 12.183 + gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; 12.184 + gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; 12.185 +} 12.186 + 12.187 +mapperMBC3 gbDataMBC3 = { 12.188 + 0, // RAM enable 12.189 + 1, // ROM bank 12.190 + 0, // RAM bank 12.191 + 0, // RAM address 12.192 + 0, // timer clock latch 12.193 + 0, // timer clock register 12.194 + 0, // timer seconds 12.195 + 0, // timer minutes 12.196 + 0, // timer hours 12.197 + 0, // timer days 12.198 + 0, // timer control 12.199 + 0, // timer latched seconds 12.200 + 0, // timer latched minutes 12.201 + 0, // timer latched hours 12.202 + 0, // timer latched days 12.203 + 0, // timer latched control 12.204 + (time_t)-1 // last time 12.205 +}; 12.206 + 12.207 +void memoryUpdateMBC3Clock() 12.208 +{ 12.209 + time_t now; 12.210 + 12.211 + if (VBAMovieActive() || VBAMovieLoading()) 12.212 + now = (time_t)(VBAMovieGetId() + VBAMovieGetFrameCounter()/60); /// FIXME: is /60 the right factor? 12.213 + else 12.214 + now = time(NULL); 12.215 + 12.216 + time_t diff = now - gbDataMBC3.mapperLastTime; 12.217 + if (diff > 0) 12.218 + { 12.219 + // update the clock according to the last update time 12.220 + gbDataMBC3.mapperSeconds += (int)(diff % 60); 12.221 + if (gbDataMBC3.mapperSeconds > 59) 12.222 + { 12.223 + gbDataMBC3.mapperSeconds -= 60; 12.224 + gbDataMBC3.mapperMinutes++; 12.225 + } 12.226 + 12.227 + diff /= 60; 12.228 + 12.229 + gbDataMBC3.mapperMinutes += (int)(diff % 60); 12.230 + if (gbDataMBC3.mapperMinutes > 60) 12.231 + { 12.232 + gbDataMBC3.mapperMinutes -= 60; 12.233 + gbDataMBC3.mapperHours++; 12.234 + } 12.235 + 12.236 + diff /= 60; 12.237 + 12.238 + gbDataMBC3.mapperHours += (int)(diff % 24); 12.239 + if (gbDataMBC3.mapperHours > 24) 12.240 + { 12.241 + gbDataMBC3.mapperHours -= 24; 12.242 + gbDataMBC3.mapperDays++; 12.243 + } 12.244 + diff /= 24; 12.245 + 12.246 + gbDataMBC3.mapperDays += (int)diff; 12.247 + if (gbDataMBC3.mapperDays > 255) 12.248 + { 12.249 + if (gbDataMBC3.mapperDays > 511) 12.250 + { 12.251 + gbDataMBC3.mapperDays %= 512; 12.252 + gbDataMBC3.mapperControl |= 0x80; 12.253 + } 12.254 + gbDataMBC3.mapperControl = (gbDataMBC3.mapperControl & 0xfe) | 12.255 + (gbDataMBC3.mapperDays > 255 ? 1 : 0); 12.256 + } 12.257 + } 12.258 + gbDataMBC3.mapperLastTime = now; 12.259 +} 12.260 + 12.261 +// MBC3 ROM write registers 12.262 +void mapperMBC3ROM(u16 address, u8 value) 12.263 +{ 12.264 + int tmpAddress = 0; 12.265 + 12.266 + switch (address & 0x6000) 12.267 + { 12.268 + case 0x0000: // RAM enable register 12.269 + gbDataMBC3.mapperRAMEnable = ((value & 0x0a) == 0x0a ? 1 : 0); 12.270 + break; 12.271 + case 0x2000: // ROM bank select 12.272 + value = value & 0x7f; 12.273 + if (value == 0) 12.274 + value = 1; 12.275 + if (value == gbDataMBC3.mapperROMBank) 12.276 + break; 12.277 + 12.278 + tmpAddress = value << 14; 12.279 + 12.280 + tmpAddress &= gbRomSizeMask; 12.281 + gbDataMBC3.mapperROMBank = value; 12.282 + gbMemoryMap[0x04] = &gbRom[tmpAddress]; 12.283 + gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; 12.284 + gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; 12.285 + gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; 12.286 + 12.287 + break; 12.288 + case 0x4000: // RAM bank select 12.289 + if (value < 8) 12.290 + { 12.291 + if (value == gbDataMBC3.mapperRAMBank) 12.292 + break; 12.293 + tmpAddress = value << 13; 12.294 + tmpAddress &= gbRamSizeMask; 12.295 + gbMemoryMap[0x0a] = &gbRam[tmpAddress]; 12.296 + gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000]; 12.297 + gbDataMBC3.mapperRAMBank = value; 12.298 + gbDataMBC3.mapperRAMAddress = tmpAddress; 12.299 + } 12.300 + else 12.301 + { 12.302 + if (gbDataMBC3.mapperRAMEnable) 12.303 + { 12.304 + gbDataMBC3.mapperRAMBank = -1; 12.305 + 12.306 + gbDataMBC3.mapperClockRegister = value; 12.307 + } 12.308 + } 12.309 + break; 12.310 + case 0x6000: // clock latch 12.311 + if (gbDataMBC3.mapperClockLatch == 0 && value == 1) 12.312 + { 12.313 + memoryUpdateMBC3Clock(); 12.314 + gbDataMBC3.mapperLSeconds = gbDataMBC3.mapperSeconds; 12.315 + gbDataMBC3.mapperLMinutes = gbDataMBC3.mapperMinutes; 12.316 + gbDataMBC3.mapperLHours = gbDataMBC3.mapperHours; 12.317 + gbDataMBC3.mapperLDays = gbDataMBC3.mapperDays; 12.318 + gbDataMBC3.mapperLControl = gbDataMBC3.mapperControl; 12.319 + } 12.320 + if (value == 0x00 || value == 0x01) 12.321 + gbDataMBC3.mapperClockLatch = value; 12.322 + break; 12.323 + } 12.324 +} 12.325 + 12.326 +// MBC3 RAM write 12.327 +void mapperMBC3RAM(u16 address, u8 value) 12.328 +{ 12.329 + if (gbDataMBC3.mapperRAMEnable) 12.330 + { 12.331 + if (gbDataMBC3.mapperRAMBank != -1) 12.332 + { 12.333 + if (gbRamSize) 12.334 + { 12.335 + gbWriteMemoryQuick(address, value); 12.336 + systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED; 12.337 + } 12.338 + } 12.339 + else 12.340 + { 12.341 + time_t tmp; //Small kludge to get it working on some 64 bit systems. 12.342 + if (VBAMovieActive() || VBAMovieLoading()) 12.343 + gbDataMBC3.mapperLastTime = VBAMovieGetId() + VBAMovieGetFrameCounter()/60; 12.344 + else { 12.345 + time(&tmp); 12.346 + gbDataMBC3.mapperLastTime=(u32)tmp; 12.347 + } 12.348 + systemScreenMessage(ctime(&tmp), 4); 12.349 + gbDataMBC3.mapperLastTime=(u32)tmp; 12.350 + 12.351 + switch (gbDataMBC3.mapperClockRegister) 12.352 + { 12.353 + case 0x08: 12.354 + gbDataMBC3.mapperSeconds = value; 12.355 + break; 12.356 + case 0x09: 12.357 + gbDataMBC3.mapperMinutes = value; 12.358 + break; 12.359 + case 0x0a: 12.360 + gbDataMBC3.mapperHours = value; 12.361 + break; 12.362 + case 0x0b: 12.363 + gbDataMBC3.mapperDays = value; 12.364 + break; 12.365 + case 0x0c: 12.366 + if (gbDataMBC3.mapperControl & 0x80) 12.367 + gbDataMBC3.mapperControl = 0x80 | value; 12.368 + else 12.369 + gbDataMBC3.mapperControl = value; 12.370 + break; 12.371 + } 12.372 + } 12.373 + } 12.374 +} 12.375 + 12.376 +// MBC3 read RAM 12.377 +u8 mapperMBC3ReadRAM(u16 address) 12.378 +{ 12.379 + if (gbDataMBC3.mapperRAMEnable) 12.380 + { 12.381 + if (gbDataMBC3.mapperRAMBank != -1) 12.382 + { 12.383 + return gbReadMemoryQuick(address); 12.384 + } 12.385 + 12.386 + switch (gbDataMBC3.mapperClockRegister) 12.387 + { 12.388 + case 0x08: 12.389 + return gbDataMBC3.mapperLSeconds; 12.390 + break; 12.391 + case 0x09: 12.392 + return gbDataMBC3.mapperLMinutes; 12.393 + break; 12.394 + case 0x0a: 12.395 + return gbDataMBC3.mapperLHours; 12.396 + break; 12.397 + case 0x0b: 12.398 + return gbDataMBC3.mapperLDays; 12.399 + break; 12.400 + case 0x0c: 12.401 + return gbDataMBC3.mapperLControl; 12.402 + } 12.403 + } 12.404 + return 0; 12.405 +} 12.406 + 12.407 +void memoryUpdateMapMBC3() 12.408 +{ 12.409 + int tmpAddress = gbDataMBC3.mapperROMBank << 14; 12.410 + 12.411 + tmpAddress &= gbRomSizeMask; 12.412 + 12.413 + gbMemoryMap[0x04] = &gbRom[tmpAddress]; 12.414 + gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; 12.415 + gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; 12.416 + gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; 12.417 + 12.418 + if (gbDataMBC3.mapperRAMBank >= 0 && gbRamSize) 12.419 + { 12.420 + tmpAddress = gbDataMBC3.mapperRAMBank << 13; 12.421 + tmpAddress &= gbRamSizeMask; 12.422 + gbMemoryMap[0x0a] = &gbRam[tmpAddress]; 12.423 + gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000]; 12.424 + } 12.425 +} 12.426 + 12.427 +mapperMBC5 gbDataMBC5 = { 12.428 + 0, // RAM enable 12.429 + 1, // ROM bank 12.430 + 0, // RAM bank 12.431 + 0, // ROM high address 12.432 + 0, // RAM address 12.433 + 0 // is rumble cartridge? 12.434 +}; 12.435 + 12.436 +// MBC5 ROM write registers 12.437 +void mapperMBC5ROM(u16 address, u8 value) 12.438 +{ 12.439 + int tmpAddress = 0; 12.440 + 12.441 + switch (address & 0x6000) 12.442 + { 12.443 + case 0x0000: // RAM enable register 12.444 + gbDataMBC5.mapperRAMEnable = ((value & 0x0a) == 0x0a ? 1 : 0); 12.445 + break; 12.446 + case 0x2000: // ROM bank select 12.447 + if (address < 0x3000) 12.448 + { 12.449 + value = value & 0xff; 12.450 + if (value == gbDataMBC5.mapperROMBank) 12.451 + break; 12.452 + 12.453 + tmpAddress = (value << 14) | (gbDataMBC5.mapperROMHighAddress << 22) ; 12.454 + 12.455 + tmpAddress &= gbRomSizeMask; 12.456 + gbDataMBC5.mapperROMBank = value; 12.457 + gbMemoryMap[0x04] = &gbRom[tmpAddress]; 12.458 + gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; 12.459 + gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; 12.460 + gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; 12.461 + } 12.462 + else 12.463 + { 12.464 + value = value & 1; 12.465 + if (value == gbDataMBC5.mapperROMHighAddress) 12.466 + break; 12.467 + 12.468 + tmpAddress = (gbDataMBC5.mapperROMBank << 14) | (value << 22); 12.469 + 12.470 + tmpAddress &= gbRomSizeMask; 12.471 + gbDataMBC5.mapperROMHighAddress = value; 12.472 + gbMemoryMap[0x04] = &gbRom[tmpAddress]; 12.473 + gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; 12.474 + gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; 12.475 + gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; 12.476 + } 12.477 + break; 12.478 + case 0x4000: // RAM bank select 12.479 + if (gbDataMBC5.isRumbleCartridge) 12.480 + value &= 0x07; 12.481 + else 12.482 + value &= 0x0f; 12.483 + if (value == gbDataMBC5.mapperRAMBank) 12.484 + break; 12.485 + tmpAddress = value << 13; 12.486 + tmpAddress &= gbRamSizeMask; 12.487 + if (gbRamSize) 12.488 + { 12.489 + gbMemoryMap[0x0a] = &gbRam[tmpAddress]; 12.490 + gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000]; 12.491 + 12.492 + gbDataMBC5.mapperRAMBank = value; 12.493 + gbDataMBC5.mapperRAMAddress = tmpAddress; 12.494 + } 12.495 + break; 12.496 + } 12.497 +} 12.498 + 12.499 +// MBC5 RAM write 12.500 +void mapperMBC5RAM(u16 address, u8 value) 12.501 +{ 12.502 + if (gbDataMBC5.mapperRAMEnable) 12.503 + { 12.504 + if (gbRamSize) 12.505 + { 12.506 + gbWriteMemoryQuick(address, value); 12.507 + systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED; 12.508 + } 12.509 + } 12.510 +} 12.511 + 12.512 +void memoryUpdateMapMBC5() 12.513 +{ 12.514 + int tmpAddress = (gbDataMBC5.mapperROMBank << 14) | 12.515 + (gbDataMBC5.mapperROMHighAddress << 22) ; 12.516 + 12.517 + tmpAddress &= gbRomSizeMask; 12.518 + gbMemoryMap[0x04] = &gbRom[tmpAddress]; 12.519 + gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; 12.520 + gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; 12.521 + gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; 12.522 + 12.523 + if (gbRamSize) 12.524 + { 12.525 + tmpAddress = gbDataMBC5.mapperRAMBank << 13; 12.526 + tmpAddress &= gbRamSizeMask; 12.527 + gbMemoryMap[0x0a] = &gbRam[tmpAddress]; 12.528 + gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000]; 12.529 + } 12.530 +} 12.531 + 12.532 +mapperMBC7 gbDataMBC7 = { 12.533 + 0, // RAM enable 12.534 + 1, // ROM bank 12.535 + 0, // RAM bank 12.536 + 0, // RAM address 12.537 + 0, // chip select 12.538 + 0, // ?? 12.539 + 0, // mapper state 12.540 + 0, // buffer for receiving serial data 12.541 + 0, // idle state 12.542 + 0, // count of bits received 12.543 + 0, // command received 12.544 + 0, // address received 12.545 + 0, // write enable 12.546 + 0, // value to return on ram 12.547 +}; 12.548 + 12.549 +// MBC7 ROM write registers 12.550 +void mapperMBC7ROM(u16 address, u8 value) 12.551 +{ 12.552 + int tmpAddress = 0; 12.553 + 12.554 + switch (address & 0x6000) 12.555 + { 12.556 + case 0x0000: 12.557 + break; 12.558 + case 0x2000: // ROM bank select 12.559 + value = value & 0x7f; 12.560 + if (value == 0) 12.561 + value = 1; 12.562 + 12.563 + if (value == gbDataMBC7.mapperROMBank) 12.564 + break; 12.565 + 12.566 + tmpAddress = (value << 14); 12.567 + 12.568 + tmpAddress &= gbRomSizeMask; 12.569 + gbDataMBC7.mapperROMBank = value; 12.570 + gbMemoryMap[0x04] = &gbRom[tmpAddress]; 12.571 + gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; 12.572 + gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; 12.573 + gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; 12.574 + break; 12.575 + case 0x4000: // RAM bank select/enable 12.576 + if (value < 8) 12.577 + { 12.578 + tmpAddress = (value&3) << 13; 12.579 + tmpAddress &= gbRamSizeMask; 12.580 + gbMemoryMap[0x0a] = &gbMemory[0xa000]; 12.581 + gbMemoryMap[0x0b] = &gbMemory[0xb000]; 12.582 + 12.583 + gbDataMBC7.mapperRAMBank = value; 12.584 + gbDataMBC7.mapperRAMAddress = tmpAddress; 12.585 + gbDataMBC7.mapperRAMEnable = 0; 12.586 + } 12.587 + else 12.588 + { 12.589 + gbDataMBC7.mapperRAMEnable = 0; 12.590 + } 12.591 + break; 12.592 + } 12.593 +} 12.594 + 12.595 +// MBC7 read RAM 12.596 +u8 mapperMBC7ReadRAM(u16 address) 12.597 +{ 12.598 + switch (address & 0xa0f0) 12.599 + { 12.600 + case 0xa000: 12.601 + case 0xa010: 12.602 + case 0xa060: 12.603 + case 0xa070: 12.604 + return 0; 12.605 + case 0xa020: 12.606 + // sensor X low byte 12.607 + return systemGetSensorX() & 255; 12.608 + case 0xa030: 12.609 + // sensor X high byte 12.610 + return systemGetSensorX() >> 8; 12.611 + case 0xa040: 12.612 + // sensor Y low byte 12.613 + return systemGetSensorY() & 255; 12.614 + case 0xa050: 12.615 + // sensor Y high byte 12.616 + return systemGetSensorY() >> 8; 12.617 + case 0xa080: 12.618 + return gbDataMBC7.value; 12.619 + } 12.620 + return 0xff; 12.621 +} 12.622 + 12.623 +// MBC7 RAM write 12.624 +void mapperMBC7RAM(u16 address, u8 value) 12.625 +{ 12.626 + if (address == 0xa080) 12.627 + { 12.628 + // special processing needed 12.629 + int oldCs = gbDataMBC7.cs, oldSk = gbDataMBC7.sk; 12.630 + 12.631 + gbDataMBC7.cs = value>>7; 12.632 + gbDataMBC7.sk = (value>>6)&1; 12.633 + 12.634 + if (!oldCs && gbDataMBC7.cs) 12.635 + { 12.636 + if (gbDataMBC7.state == 5) 12.637 + { 12.638 + if (gbDataMBC7.writeEnable) 12.639 + { 12.640 + gbWriteMemoryQuick(0xa000+gbDataMBC7.address*2, gbDataMBC7.buffer>>8); 12.641 + gbWriteMemoryQuick(0xa000+gbDataMBC7.address*2+1, gbDataMBC7.buffer&0xff); 12.642 + systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED; 12.643 + } 12.644 + gbDataMBC7.state = 0; 12.645 + gbDataMBC7.value = 1; 12.646 + } 12.647 + else 12.648 + { 12.649 + gbDataMBC7.idle = true; 12.650 + gbDataMBC7.state = 0; 12.651 + } 12.652 + } 12.653 + 12.654 + if (!oldSk && gbDataMBC7.sk) 12.655 + { 12.656 + if (gbDataMBC7.idle) 12.657 + { 12.658 + if (value & 0x02) 12.659 + { 12.660 + gbDataMBC7.idle = false; 12.661 + gbDataMBC7.count = 0; 12.662 + gbDataMBC7.state = 1; 12.663 + } 12.664 + } 12.665 + else 12.666 + { 12.667 + switch (gbDataMBC7.state) 12.668 + { 12.669 + case 1: 12.670 + // receiving command 12.671 + gbDataMBC7.buffer <<= 1; 12.672 + gbDataMBC7.buffer |= (value & 0x02) ? 1 : 0; 12.673 + gbDataMBC7.count++; 12.674 + if (gbDataMBC7.count == 2) 12.675 + { 12.676 + // finished receiving command 12.677 + gbDataMBC7.state = 2; 12.678 + gbDataMBC7.count = 0; 12.679 + gbDataMBC7.code = gbDataMBC7.buffer & 3; 12.680 + } 12.681 + break; 12.682 + case 2: 12.683 + // receive address 12.684 + gbDataMBC7.buffer <<= 1; 12.685 + gbDataMBC7.buffer |= (value&0x02) ? 1 : 0; 12.686 + gbDataMBC7.count++; 12.687 + if (gbDataMBC7.count == 8) 12.688 + { 12.689 + // finish receiving 12.690 + gbDataMBC7.state = 3; 12.691 + gbDataMBC7.count = 0; 12.692 + gbDataMBC7.address = gbDataMBC7.buffer&0xff; 12.693 + if (gbDataMBC7.code == 0) 12.694 + { 12.695 + if ((gbDataMBC7.address>>6) == 0) 12.696 + { 12.697 + gbDataMBC7.writeEnable = 0; 12.698 + gbDataMBC7.state = 0; 12.699 + } 12.700 + else if ((gbDataMBC7.address>>6) == 3) 12.701 + { 12.702 + gbDataMBC7.writeEnable = 1; 12.703 + gbDataMBC7.state = 0; 12.704 + } 12.705 + } 12.706 + } 12.707 + break; 12.708 + case 3: 12.709 + gbDataMBC7.buffer <<= 1; 12.710 + gbDataMBC7.buffer |= (value&0x02) ? 1 : 0; 12.711 + gbDataMBC7.count++; 12.712 + 12.713 + switch (gbDataMBC7.code) 12.714 + { 12.715 + case 0: 12.716 + if (gbDataMBC7.count == 16) 12.717 + { 12.718 + if ((gbDataMBC7.address>>6) == 0) 12.719 + { 12.720 + gbDataMBC7.writeEnable = 0; 12.721 + gbDataMBC7.state = 0; 12.722 + } 12.723 + else if ((gbDataMBC7.address>>6) == 1) 12.724 + { 12.725 + if (gbDataMBC7.writeEnable) 12.726 + { 12.727 + for (int i = 0; i < 256; i++) 12.728 + { 12.729 + gbWriteMemoryQuick(0xa000+i*2, gbDataMBC7.buffer >> 8); 12.730 + gbWriteMemoryQuick(0xa000+i*2+1, gbDataMBC7.buffer & 0xff); 12.731 + systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED; 12.732 + } 12.733 + } 12.734 + gbDataMBC7.state = 5; 12.735 + } 12.736 + else if ((gbDataMBC7.address>>6) == 2) 12.737 + { 12.738 + if (gbDataMBC7.writeEnable) 12.739 + { 12.740 + for (int i = 0; i < 256; i++) 12.741 + WRITE16LE((u16 *)&gbMemory[0xa000+i*2], 0xffff); 12.742 + systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED; 12.743 + } 12.744 + gbDataMBC7.state = 5; 12.745 + } 12.746 + else if ((gbDataMBC7.address>>6) == 3) 12.747 + { 12.748 + gbDataMBC7.writeEnable = 1; 12.749 + gbDataMBC7.state = 0; 12.750 + } 12.751 + gbDataMBC7.count = 0; 12.752 + } 12.753 + break; 12.754 + case 1: 12.755 + if (gbDataMBC7.count == 16) 12.756 + { 12.757 + gbDataMBC7.count = 0; 12.758 + gbDataMBC7.state = 5; 12.759 + gbDataMBC7.value = 0; 12.760 + } 12.761 + break; 12.762 + case 2: 12.763 + if (gbDataMBC7.count == 1) 12.764 + { 12.765 + gbDataMBC7.state = 4; 12.766 + gbDataMBC7.count = 0; 12.767 + gbDataMBC7.buffer = (gbReadMemoryQuick(0xa000+gbDataMBC7.address*2)<<8)| 12.768 + (gbReadMemoryQuick(0xa000+gbDataMBC7.address*2+1)); 12.769 + } 12.770 + break; 12.771 + case 3: 12.772 + if (gbDataMBC7.count == 16) 12.773 + { 12.774 + gbDataMBC7.count = 0; 12.775 + gbDataMBC7.state = 5; 12.776 + gbDataMBC7.value = 0; 12.777 + gbDataMBC7.buffer = 0xffff; 12.778 + } 12.779 + break; 12.780 + } 12.781 + break; 12.782 + } 12.783 + } 12.784 + } 12.785 + 12.786 + if (oldSk && !gbDataMBC7.sk) 12.787 + { 12.788 + if (gbDataMBC7.state == 4) 12.789 + { 12.790 + gbDataMBC7.value = (gbDataMBC7.buffer & 0x8000) ? 1 : 0; 12.791 + gbDataMBC7.buffer <<= 1; 12.792 + gbDataMBC7.count++; 12.793 + if (gbDataMBC7.count == 16) 12.794 + { 12.795 + gbDataMBC7.count = 0; 12.796 + gbDataMBC7.state = 0; 12.797 + } 12.798 + } 12.799 + } 12.800 + } 12.801 +} 12.802 + 12.803 +void memoryUpdateMapMBC7() 12.804 +{ 12.805 + int tmpAddress = (gbDataMBC5.mapperROMBank << 14); 12.806 + 12.807 + tmpAddress &= gbRomSizeMask; 12.808 + gbMemoryMap[0x04] = &gbRom[tmpAddress]; 12.809 + gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; 12.810 + gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; 12.811 + gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; 12.812 +} 12.813 + 12.814 +mapperHuC1 gbDataHuC1 = { 12.815 + 0, // RAM enable 12.816 + 1, // ROM bank 12.817 + 0, // RAM bank 12.818 + 0, // memory model 12.819 + 0, // ROM high address 12.820 + 0 // RAM address 12.821 +}; 12.822 + 12.823 +// HuC1 ROM write registers 12.824 +void mapperHuC1ROM(u16 address, u8 value) 12.825 +{ 12.826 + int tmpAddress = 0; 12.827 + 12.828 + switch (address & 0x6000) 12.829 + { 12.830 + case 0x0000: // RAM enable register 12.831 + gbDataHuC1.mapperRAMEnable = ((value & 0x0a) == 0x0a ? 1 : 0); 12.832 + break; 12.833 + case 0x2000: // ROM bank select 12.834 + value = value & 0x3f; 12.835 + if (value == 0) 12.836 + value = 1; 12.837 + if (value == gbDataHuC1.mapperROMBank) 12.838 + break; 12.839 + 12.840 + tmpAddress = value << 14; 12.841 + 12.842 + tmpAddress &= gbRomSizeMask; 12.843 + gbDataHuC1.mapperROMBank = value; 12.844 + gbMemoryMap[0x04] = &gbRom[tmpAddress]; 12.845 + gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; 12.846 + gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; 12.847 + gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; 12.848 + break; 12.849 + case 0x4000: // RAM bank select 12.850 + if (gbDataHuC1.mapperMemoryModel == 1) 12.851 + { 12.852 + // 4/32 model, RAM bank switching provided 12.853 + value = value & 0x03; 12.854 + if (value == gbDataHuC1.mapperRAMBank) 12.855 + break; 12.856 + tmpAddress = value << 13; 12.857 + tmpAddress &= gbRamSizeMask; 12.858 + gbMemoryMap[0x0a] = &gbRam[tmpAddress]; 12.859 + gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000]; 12.860 + gbDataHuC1.mapperRAMBank = value; 12.861 + gbDataHuC1.mapperRAMAddress = tmpAddress; 12.862 + } 12.863 + else 12.864 + { 12.865 + // 16/8, set the high address 12.866 + gbDataHuC1.mapperROMHighAddress = value & 0x03; 12.867 + tmpAddress = gbDataHuC1.mapperROMBank << 14; 12.868 + tmpAddress |= (gbDataHuC1.mapperROMHighAddress) << 19; 12.869 + tmpAddress &= gbRomSizeMask; 12.870 + gbMemoryMap[0x04] = &gbRom[tmpAddress]; 12.871 + gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; 12.872 + gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; 12.873 + gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; 12.874 + } 12.875 + break; 12.876 + case 0x6000: // memory model select 12.877 + gbDataHuC1.mapperMemoryModel = value & 1; 12.878 + break; 12.879 + } 12.880 +} 12.881 + 12.882 +// HuC1 RAM write 12.883 +void mapperHuC1RAM(u16 address, u8 value) 12.884 +{ 12.885 + if (gbDataHuC1.mapperRAMEnable) 12.886 + { 12.887 + if (gbRamSize) 12.888 + { 12.889 + gbWriteMemoryQuick(address, value); 12.890 + systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED; 12.891 + } 12.892 + } 12.893 +} 12.894 + 12.895 +void memoryUpdateMapHuC1() 12.896 +{ 12.897 + int tmpAddress = gbDataHuC1.mapperROMBank << 14; 12.898 + 12.899 + tmpAddress &= gbRomSizeMask; 12.900 + 12.901 + gbMemoryMap[0x04] = &gbRom[tmpAddress]; 12.902 + gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; 12.903 + gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; 12.904 + gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; 12.905 + 12.906 + if (gbRamSize) 12.907 + { 12.908 + tmpAddress = gbDataHuC1.mapperRAMBank << 13; 12.909 + tmpAddress &= gbRamSizeMask; 12.910 + gbMemoryMap[0x0a] = &gbRam[tmpAddress]; 12.911 + gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000]; 12.912 + } 12.913 +} 12.914 + 12.915 +mapperHuC3 gbDataHuC3 = { 12.916 + 0, // RAM enable 12.917 + 1, // ROM bank 12.918 + 0, // RAM bank 12.919 + 0, // RAM address 12.920 + 0, // RAM flag 12.921 + 0 // RAM read value 12.922 +}; 12.923 + 12.924 +// HuC3 ROM write registers 12.925 +void mapperHuC3ROM(u16 address, u8 value) 12.926 +{ 12.927 + int tmpAddress = 0; 12.928 + 12.929 + switch (address & 0x6000) 12.930 + { 12.931 + case 0x0000: // RAM enable register 12.932 + gbDataHuC3.mapperRAMEnable = (value == 0x0a ? 1 : 0); 12.933 + gbDataHuC3.mapperRAMFlag = value; 12.934 + if (gbDataHuC3.mapperRAMFlag != 0x0a) 12.935 + gbDataHuC3.mapperRAMBank = -1; 12.936 + break; 12.937 + case 0x2000: // ROM bank select 12.938 + value = value & 0x7f; 12.939 + if (value == 0) 12.940 + value = 1; 12.941 + if (value == gbDataHuC3.mapperROMBank) 12.942 + break; 12.943 + 12.944 + tmpAddress = value << 14; 12.945 + 12.946 + tmpAddress &= gbRomSizeMask; 12.947 + gbDataHuC3.mapperROMBank = value; 12.948 + gbMemoryMap[0x04] = &gbRom[tmpAddress]; 12.949 + gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; 12.950 + gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; 12.951 + gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; 12.952 + break; 12.953 + case 0x4000: // RAM bank select 12.954 + value = value & 0x03; 12.955 + if (value == gbDataHuC3.mapperRAMBank) 12.956 + break; 12.957 + tmpAddress = value << 13; 12.958 + tmpAddress &= gbRamSizeMask; 12.959 + gbMemoryMap[0x0a] = &gbRam[tmpAddress]; 12.960 + gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000]; 12.961 + gbDataHuC3.mapperRAMBank = value; 12.962 + gbDataHuC3.mapperRAMAddress = tmpAddress; 12.963 + break; 12.964 + case 0x6000: // nothing to do! 12.965 + break; 12.966 + } 12.967 +} 12.968 + 12.969 +// HuC3 read RAM 12.970 +u8 mapperHuC3ReadRAM(u16 address) 12.971 +{ 12.972 + if (gbDataHuC3.mapperRAMFlag > 0x0b && 12.973 + gbDataHuC3.mapperRAMFlag < 0x0e) 12.974 + { 12.975 + if (gbDataHuC3.mapperRAMFlag != 0x0c) 12.976 + return 1; 12.977 + return gbDataHuC3.mapperRAMValue; 12.978 + } 12.979 + else 12.980 + return gbReadMemoryQuick(address); 12.981 +} 12.982 + 12.983 +// HuC3 RAM write 12.984 +void mapperHuC3RAM(u16 address, u8 value) 12.985 +{ 12.986 + int32 *p; 12.987 + 12.988 + if (gbDataHuC3.mapperRAMFlag < 0x0b || 12.989 + gbDataHuC3.mapperRAMFlag > 0x0e) 12.990 + { 12.991 + if (gbDataHuC3.mapperRAMEnable) 12.992 + { 12.993 + if (gbRamSize) 12.994 + { 12.995 + gbWriteMemoryQuick(address, value); 12.996 + systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED; 12.997 + } 12.998 + } 12.999 + } 12.1000 + else 12.1001 + { 12.1002 + if (gbDataHuC3.mapperRAMFlag == 0x0b) 12.1003 + { 12.1004 + if (value == 0x62) 12.1005 + { 12.1006 + gbDataHuC3.mapperRAMValue = 1; 12.1007 + } 12.1008 + else 12.1009 + { 12.1010 + switch (value & 0xf0) 12.1011 + { 12.1012 + case 0x10: 12.1013 + p = &gbDataHuC3.mapperRegister2; 12.1014 + gbDataHuC3.mapperRAMValue = *(p+gbDataHuC3.mapperRegister1++); 12.1015 + if (gbDataHuC3.mapperRegister1 > 6) 12.1016 + gbDataHuC3.mapperRegister1 = 0; 12.1017 + break; 12.1018 + case 0x30: 12.1019 + p = &gbDataHuC3.mapperRegister2; 12.1020 + *(p+gbDataHuC3.mapperRegister1++) = value & 0x0f; 12.1021 + if (gbDataHuC3.mapperRegister1 > 6) 12.1022 + gbDataHuC3.mapperRegister1 = 0; 12.1023 + gbDataHuC3.mapperAddress = 12.1024 + (gbDataHuC3.mapperRegister6 << 24) | 12.1025 + (gbDataHuC3.mapperRegister5 << 16) | 12.1026 + (gbDataHuC3.mapperRegister4 << 8) | 12.1027 + (gbDataHuC3.mapperRegister3 << 4) | 12.1028 + (gbDataHuC3.mapperRegister2); 12.1029 + break; 12.1030 + case 0x40: 12.1031 + gbDataHuC3.mapperRegister1 = (gbDataHuC3.mapperRegister1 & 0xf0) | 12.1032 + (value & 0x0f); 12.1033 + gbDataHuC3.mapperRegister2 = (gbDataHuC3.mapperAddress & 0x0f); 12.1034 + gbDataHuC3.mapperRegister3 = ((gbDataHuC3.mapperAddress>>4)&0x0f); 12.1035 + gbDataHuC3.mapperRegister4 = ((gbDataHuC3.mapperAddress>>8)&0x0f); 12.1036 + gbDataHuC3.mapperRegister5 = ((gbDataHuC3.mapperAddress>>16)&0x0f); 12.1037 + gbDataHuC3.mapperRegister6 = ((gbDataHuC3.mapperAddress>>24)&0x0f); 12.1038 + gbDataHuC3.mapperRegister7 = 0; 12.1039 + gbDataHuC3.mapperRegister8 = 0; 12.1040 + gbDataHuC3.mapperRAMValue = 0; 12.1041 + break; 12.1042 + case 0x50: 12.1043 + gbDataHuC3.mapperRegister1 = (gbDataHuC3.mapperRegister1 & 0x0f) | 12.1044 + ((value << 4)&0x0f); 12.1045 + break; 12.1046 + default: 12.1047 + gbDataHuC3.mapperRAMValue = 1; 12.1048 + break; 12.1049 + } 12.1050 + } 12.1051 + } 12.1052 + } 12.1053 +} 12.1054 + 12.1055 +void memoryUpdateMapHuC3() 12.1056 +{ 12.1057 + int tmpAddress = gbDataHuC3.mapperROMBank << 14; 12.1058 + 12.1059 + tmpAddress &= gbRomSizeMask; 12.1060 + gbMemoryMap[0x04] = &gbRom[tmpAddress]; 12.1061 + gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; 12.1062 + gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; 12.1063 + gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; 12.1064 + 12.1065 + if (gbRamSize) 12.1066 + { 12.1067 + tmpAddress = gbDataHuC3.mapperRAMBank << 13; 12.1068 + tmpAddress &= gbRamSizeMask; 12.1069 + gbMemoryMap[0x0a] = &gbRam[tmpAddress]; 12.1070 + gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000]; 12.1071 + } 12.1072 +} 12.1073 +
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 13.2 +++ b/src/gb/gbMemory.h Sat Mar 03 11:44:47 2012 -0600 13.3 @@ -0,0 +1,142 @@ 13.4 +#ifndef VBA_GB_MEMORY_H 13.5 +#define VBA_GB_MEMORY_H 13.6 + 13.7 +#if _MSC_VER > 1000 13.8 +#pragma once 13.9 +#endif // _MSC_VER > 1000 13.10 + 13.11 +#include "../Port.h" 13.12 + 13.13 +struct mapperMBC1 13.14 +{ 13.15 + int32 mapperRAMEnable; 13.16 + int32 mapperROMBank; 13.17 + int32 mapperRAMBank; 13.18 + int32 mapperMemoryModel; 13.19 + int32 mapperROMHighAddress; 13.20 + int32 mapperRAMAddress; 13.21 +}; 13.22 + 13.23 +struct mapperMBC2 13.24 +{ 13.25 + int32 mapperRAMEnable; 13.26 + int32 mapperROMBank; 13.27 +}; 13.28 + 13.29 +struct mapperMBC3 13.30 +{ 13.31 + int32 mapperRAMEnable; 13.32 + int32 mapperROMBank; 13.33 + int32 mapperRAMBank; 13.34 + int32 mapperRAMAddress; 13.35 + int32 mapperClockLatch; 13.36 + int32 mapperClockRegister; 13.37 + int32 mapperSeconds; 13.38 + int32 mapperMinutes; 13.39 + int32 mapperHours; 13.40 + int32 mapperDays; 13.41 + int32 mapperControl; 13.42 + int32 mapperLSeconds; 13.43 + int32 mapperLMinutes; 13.44 + int32 mapperLHours; 13.45 + int32 mapperLDays; 13.46 + int32 mapperLControl; 13.47 + //time_t mapperLastTime; 13.48 + u32 mapperLastTime; 13.49 +}; 13.50 + 13.51 +struct mapperMBC5 13.52 +{ 13.53 + int32 mapperRAMEnable; 13.54 + int32 mapperROMBank; 13.55 + int32 mapperRAMBank; 13.56 + int32 mapperROMHighAddress; 13.57 + int32 mapperRAMAddress; 13.58 + int32 isRumbleCartridge; 13.59 +}; 13.60 + 13.61 +struct mapperMBC7 13.62 +{ 13.63 + int32 mapperRAMEnable; 13.64 + int32 mapperROMBank; 13.65 + int32 mapperRAMBank; 13.66 + int32 mapperRAMAddress; 13.67 + int32 cs; 13.68 + int32 sk; 13.69 + int32 state; 13.70 + int32 buffer; 13.71 + int32 idle; 13.72 + int32 count; 13.73 + int32 code; 13.74 + int32 address; 13.75 + int32 writeEnable; 13.76 + int32 value; 13.77 +}; 13.78 + 13.79 +struct mapperHuC1 13.80 +{ 13.81 + int32 mapperRAMEnable; 13.82 + int32 mapperROMBank; 13.83 + int32 mapperRAMBank; 13.84 + int32 mapperMemoryModel; 13.85 + int32 mapperROMHighAddress; 13.86 + int32 mapperRAMAddress; 13.87 +}; 13.88 + 13.89 +struct mapperHuC3 13.90 +{ 13.91 + int32 mapperRAMEnable; 13.92 + int32 mapperROMBank; 13.93 + int32 mapperRAMBank; 13.94 + int32 mapperRAMAddress; 13.95 + int32 mapperAddress; 13.96 + int32 mapperRAMFlag; 13.97 + int32 mapperRAMValue; 13.98 + int32 mapperRegister1; 13.99 + int32 mapperRegister2; 13.100 + int32 mapperRegister3; 13.101 + int32 mapperRegister4; 13.102 + int32 mapperRegister5; 13.103 + int32 mapperRegister6; 13.104 + int32 mapperRegister7; 13.105 + int32 mapperRegister8; 13.106 +}; 13.107 + 13.108 +extern mapperMBC1 gbDataMBC1; 13.109 +extern mapperMBC2 gbDataMBC2; 13.110 +extern mapperMBC3 gbDataMBC3; 13.111 +extern mapperMBC5 gbDataMBC5; 13.112 +extern mapperHuC1 gbDataHuC1; 13.113 +extern mapperHuC3 gbDataHuC3; 13.114 + 13.115 +void mapperMBC1ROM(u16, u8); 13.116 +void mapperMBC1RAM(u16, u8); 13.117 +void mapperMBC2ROM(u16, u8); 13.118 +void mapperMBC2RAM(u16, u8); 13.119 +void mapperMBC3ROM(u16, u8); 13.120 +void mapperMBC3RAM(u16, u8); 13.121 +u8 mapperMBC3ReadRAM(u16); 13.122 +void mapperMBC5ROM(u16, u8); 13.123 +void mapperMBC5RAM(u16, u8); 13.124 +void mapperMBC7ROM(u16, u8); 13.125 +void mapperMBC7RAM(u16, u8); 13.126 +u8 mapperMBC7ReadRAM(u16); 13.127 +void mapperHuC1ROM(u16, u8); 13.128 +void mapperHuC1RAM(u16, u8); 13.129 +void mapperHuC3ROM(u16, u8); 13.130 +void mapperHuC3RAM(u16, u8); 13.131 +u8 mapperHuC3ReadRAM(u16); 13.132 + 13.133 +//extern void (*mapper)(u16,u8); 13.134 +//extern void (*mapperRAM)(u16,u8); 13.135 +//extern u8 (*mapperReadRAM)(u16); 13.136 + 13.137 +extern void memoryUpdateMapMBC1(); 13.138 +extern void memoryUpdateMapMBC2(); 13.139 +extern void memoryUpdateMapMBC3(); 13.140 +extern void memoryUpdateMapMBC5(); 13.141 +extern void memoryUpdateMapMBC7(); 13.142 +extern void memoryUpdateMapHuC1(); 13.143 +extern void memoryUpdateMapHuC3(); 13.144 + 13.145 +#endif // VBA_GB_MEMORY
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 14.2 +++ b/src/gb/gbPrinter.cpp Sat Mar 03 11:44:47 2012 -0600 14.3 @@ -0,0 +1,234 @@ 14.4 +#include <cstdio> 14.5 +#include <cstring> 14.6 + 14.7 +#include "../common/System.h" 14.8 +#include "gbPrinter.h" 14.9 + 14.10 +u8 gbPrinterStatus = 0; 14.11 +int gbPrinterState = 0; 14.12 +u8 gbPrinterData[0x280*9]; 14.13 +u8 gbPrinterPacket[0x400]; 14.14 +int gbPrinterCount = 0; 14.15 +int gbPrinterDataCount = 0; 14.16 +int gbPrinterDataSize = 0; 14.17 +int gbPrinterResult = 0; 14.18 + 14.19 +bool gbPrinterCheckCRC() 14.20 +{ 14.21 + u16 crc = 0; 14.22 + 14.23 + for (int i = 2; i < (6+gbPrinterDataSize); i++) 14.24 + { 14.25 + crc += gbPrinterPacket[i]; 14.26 + } 14.27 + 14.28 + int msgCrc = gbPrinterPacket[6+gbPrinterDataSize] + 14.29 + (gbPrinterPacket[7+gbPrinterDataSize]<<8); 14.30 + 14.31 + return msgCrc == crc; 14.32 +} 14.33 + 14.34 +void gbPrinterReset() 14.35 +{ 14.36 + gbPrinterState = 0; 14.37 + gbPrinterDataSize = 0; 14.38 + gbPrinterDataCount = 0; 14.39 + gbPrinterCount = 0; 14.40 + gbPrinterStatus = 0; 14.41 + gbPrinterResult = 0; 14.42 +} 14.43 + 14.44 +void gbPrinterShowData() 14.45 +{ 14.46 + systemGbPrint(gbPrinterData, 14.47 + gbPrinterPacket[6], 14.48 + gbPrinterPacket[7], 14.49 + gbPrinterPacket[8], 14.50 + gbPrinterPacket[9]); 14.51 + /* 14.52 + allegro_init(); 14.53 + install_keyboard(); 14.54 + set_gfx_mode(GFX_AUTODETECT, 160, 144, 0, 0); 14.55 + PALETTE pal; 14.56 + pal[0].r = 255; 14.57 + pal[0].g = 255; 14.58 + pal[0].b = 255; 14.59 + pal[1].r = 168; 14.60 + pal[1].g = 168; 14.61 + pal[1].b = 168; 14.62 + pal[2].r = 96; 14.63 + pal[2].g = 96; 14.64 + pal[2].b = 96; 14.65 + pal[3].r = 0; 14.66 + pal[3].g = 0; 14.67 + pal[3].b = 0; 14.68 + set_palette(pal); 14.69 + acquire_screen(); 14.70 + u8 *data = gbPrinterData; 14.71 + for(int y = 0; y < 0x12; y++) { 14.72 + for(int x = 0; x < 0x14; x++) { 14.73 + for(int k = 0; k < 8; k++) { 14.74 + int a = *data++; 14.75 + int b = *data++; 14.76 + for(int j = 0; j < 8; j++) { 14.77 + int mask = 1 << (7-j); 14.78 + int c = 0; 14.79 + if(a & mask) 14.80 + c++; 14.81 + if(b & mask) 14.82 + c+=2; 14.83 + putpixel(screen, x*8+j, y*8+k, c); 14.84 + } 14.85 + } 14.86 + } 14.87 + } 14.88 + release_screen(); 14.89 + while(!keypressed()) { 14.90 + } 14.91 + */ 14.92 +} 14.93 + 14.94 +void gbPrinterReceiveData() 14.95 +{ 14.96 + if (gbPrinterPacket[3]) // compressed 14.97 + { 14.98 + u8 *data = &gbPrinterPacket[6]; 14.99 + u8 *dest = &gbPrinterData[gbPrinterDataCount]; 14.100 + int len = 0; 14.101 + while (len < gbPrinterDataSize) 14.102 + { 14.103 + u8 control = *data++; 14.104 + if (control & 0x80) // repeated data 14.105 + { 14.106 + control &= 0x7f; 14.107 + control += 2; 14.108 + memset(dest, *data++, control); 14.109 + len += control; 14.110 + dest += control; 14.111 + } 14.112 + else // raw data 14.113 + { 14.114 + control++; 14.115 + memcpy(dest, data, control); 14.116 + dest += control; 14.117 + data += control; 14.118 + len += control; 14.119 + } 14.120 + } 14.121 + } 14.122 + else 14.123 + { 14.124 + memcpy(&gbPrinterData[gbPrinterDataCount], 14.125 + &gbPrinterPacket[6], 14.126 + gbPrinterDataSize); 14.127 + gbPrinterDataCount += gbPrinterDataSize; 14.128 + } 14.129 +} 14.130 + 14.131 +void gbPrinterCommand() 14.132 +{ 14.133 + switch (gbPrinterPacket[2]) 14.134 + { 14.135 + case 0x01: 14.136 + // reset/initialize packet 14.137 + gbPrinterDataCount = 0; 14.138 + gbPrinterStatus = 0; 14.139 + break; 14.140 + case 0x02: 14.141 + // print packet 14.142 + gbPrinterShowData(); 14.143 + break; 14.144 + case 0x04: 14.145 + // data packet 14.146 + gbPrinterReceiveData(); 14.147 + break; 14.148 + case 0x0f: 14.149 + // NUL packet 14.150 + break; 14.151 + } 14.152 +} 14.153 + 14.154 +u8 gbPrinterSend(u8 byte) 14.155 +{ 14.156 + switch (gbPrinterState) 14.157 + { 14.158 + case 0: 14.159 + gbPrinterCount = 0; 14.160 + // receiving preamble 14.161 + if (byte == 0x88) 14.162 + { 14.163 + gbPrinterPacket[gbPrinterCount++] = byte; 14.164 + gbPrinterState++; 14.165 + } 14.166 + else 14.167 + { 14.168 + // todo: handle failure 14.169 + gbPrinterReset(); 14.170 + } 14.171 + break; 14.172 + case 1: 14.173 + // receiving preamble 14.174 + if (byte == 0x33) 14.175 + { 14.176 + gbPrinterPacket[gbPrinterCount++] = byte; 14.177 + gbPrinterState++; 14.178 + } 14.179 + else 14.180 + { 14.181 + // todo: handle failure 14.182 + gbPrinterReset(); 14.183 + } 14.184 + break; 14.185 + case 2: 14.186 + // receiving header 14.187 + gbPrinterPacket[gbPrinterCount++] = byte; 14.188 + if (gbPrinterCount == 6) 14.189 + { 14.190 + gbPrinterState++; 14.191 + gbPrinterDataSize = gbPrinterPacket[4] + (gbPrinterPacket[5]<<8); 14.192 + } 14.193 + break; 14.194 + case 3: 14.195 + // receiving data 14.196 + if (gbPrinterDataSize) 14.197 + { 14.198 + gbPrinterPacket[gbPrinterCount++] = byte; 14.199 + if (gbPrinterCount == (6+gbPrinterDataSize)) 14.200 + { 14.201 + gbPrinterState++; 14.202 + } 14.203 + break; 14.204 + } 14.205 + gbPrinterState++; 14.206 + // intentionally move to next if no data to receive 14.207 + case 4: 14.208 + // receiving CRC 14.209 + gbPrinterPacket[gbPrinterCount++] = byte; 14.210 + gbPrinterState++; 14.211 + break; 14.212 + case 5: 14.213 + // receiving CRC-2 14.214 + gbPrinterPacket[gbPrinterCount++] = byte; 14.215 + if (gbPrinterCheckCRC()) 14.216 + { 14.217 + gbPrinterCommand(); 14.218 + } 14.219 + gbPrinterState++; 14.220 + break; 14.221 + case 6: 14.222 + // receiving dummy 1 14.223 + gbPrinterPacket[gbPrinterCount++] = byte; 14.224 + gbPrinterResult = 0x81; 14.225 + gbPrinterState++; 14.226 + break; 14.227 + case 7: 14.228 + // receiving dummy 2 14.229 + gbPrinterPacket[gbPrinterCount++] = byte; 14.230 + gbPrinterResult = gbPrinterStatus; 14.231 + gbPrinterState = 0; 14.232 + gbPrinterCount = 0; 14.233 + break; 14.234 + } 14.235 + return gbPrinterResult; 14.236 +} 14.237 +
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 15.2 +++ b/src/gb/gbPrinter.h Sat Mar 03 11:44:47 2012 -0600 15.3 @@ -0,0 +1,10 @@ 15.4 +#ifndef VBA_GB_PRINTER_H 15.5 +#define VBA_GB_PRINTER_H 15.6 + 15.7 +#if _MSC_VER > 1000 15.8 +#pragma once 15.9 +#endif // _MSC_VER > 1000 15.10 + 15.11 +extern u8 gbPrinterSend(u8 byte); 15.12 + 15.13 +#endif // VBA_GB_PRINTER_H
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 16.2 +++ b/src/gb/gbSGB.cpp Sat Mar 03 11:44:47 2012 -0600 16.3 @@ -0,0 +1,997 @@ 16.4 +#include <cstdlib> 16.5 +#include <cstring> 16.6 + 16.7 +#include "../common/System.h" 16.8 +#include "../common/Util.h" 16.9 +#include "GB.h" 16.10 +#include "gbGlobals.h" 16.11 +#include "../common/movie.h" 16.12 + 16.13 +extern u8 * pix; 16.14 + 16.15 +#define GBSGB_NONE 0 16.16 +#define GBSGB_RESET 1 16.17 +#define GBSGB_PACKET_TRANSMIT 2 16.18 + 16.19 +u8 gbSgbBorderChar [32 * 256]; 16.20 +u8 gbSgbBorder [2048]; 16.21 + 16.22 +int32 gbSgbCGBSupport = 0; 16.23 +int32 gbSgbMask = 0; 16.24 +int32 gbSgbMode = 0; 16.25 +int32 gbSgbPacketState = GBSGB_NONE; 16.26 +int32 gbSgbBit = 0; 16.27 +int32 gbSgbPacketTimeout = 0; 16.28 +int32 GBSGB_PACKET_TIMEOUT = 66666; 16.29 +u8 gbSgbPacket[16 * 7]; 16.30 +int32 gbSgbPacketNBits = 0; 16.31 +int32 gbSgbPacketByte = 0; 16.32 +int32 gbSgbPacketNumber = 0; 16.33 +int32 gbSgbMultiplayer = 0; 16.34 +int32 gbSgbFourPlayers = 0; 16.35 +u8 gbSgbNextController = 0x0f; 16.36 +u8 gbSgbReadingController = 0; 16.37 +u16 gbSgbSCPPalette[4 * 512]; 16.38 +u8 gbSgbATF[20 * 18]; 16.39 +u8 gbSgbATFList[45 * 20 * 18]; 16.40 +u8 gbSgbScreenBuffer[4160]; 16.41 + 16.42 +inline void gbSgbDraw24Bit(u8 *p, u16 v) 16.43 +{ 16.44 + *((u32 *) p) = systemColorMap32[v]; 16.45 +} 16.46 + 16.47 +inline void gbSgbDraw32Bit(u32 *p, u16 v) 16.48 +{ 16.49 + *p = systemColorMap32[v]; 16.50 +} 16.51 + 16.52 +inline void gbSgbDraw16Bit(u16 *p, u16 v) 16.53 +{ 16.54 + *p = systemColorMap16[v]; 16.55 +} 16.56 + 16.57 +void gbSgbReset() 16.58 +{ 16.59 + gbSgbPacketTimeout = 0; 16.60 + gbSgbCGBSupport = 0; 16.61 + gbSgbMask = 0; 16.62 + gbSgbPacketState = GBSGB_NONE; 16.63 + gbSgbBit = 0; 16.64 + gbSgbPacketNBits = 0; 16.65 + gbSgbPacketNumber = 0; 16.66 + gbSgbMultiplayer = 0; 16.67 + gbSgbFourPlayers = 0; 16.68 + gbSgbNextController = 0x0f; 16.69 + gbSgbReadingController = 0; 16.70 + 16.71 + memset(gbSgbSCPPalette, 0, 512 * 4); 16.72 + memset(gbSgbATF, 0, 20 * 18); 16.73 + memset(gbSgbATFList, 0, 45 * 20 * 18); 16.74 + memset(gbSgbPacket, 0, 16 * 7); 16.75 + memset(gbSgbBorderChar, 0, 32 * 256); 16.76 + memset(gbSgbBorder, 0, 2048); 16.77 + 16.78 + int i; 16.79 + for (i = 1; i < 2048; i += 2) 16.80 + { 16.81 + gbSgbBorder[i] = 1 << 2; 16.82 + } 16.83 + 16.84 + for (i = 0; i < 4; i++) 16.85 + { 16.86 + gbPalette[i * 4] = (0x1f) | (0x1f << 5) | (0x1f << 10); 16.87 + gbPalette[i * 4 + 1] = (0x15) | (0x15 << 5) | (0x15 << 10); 16.88 + gbPalette[i * 4 + 2] = (0x0c) | (0x0c << 5) | (0x0c << 10); 16.89 + gbPalette[i * 4 + 3] = 0; 16.90 + } 16.91 +} 16.92 + 16.93 +void gbSgbInit() 16.94 +{ 16.95 + gbSgbReset(); 16.96 +} 16.97 + 16.98 +void gbSgbShutdown() 16.99 +{ 16.100 + memset(gbSgbBorderChar, 0, 32 * 256); 16.101 + memset(gbSgbBorder, 0, 2048); 16.102 +} 16.103 + 16.104 +void gbSgbFillScreen(u16 color) 16.105 +{ 16.106 + switch (systemColorDepth) 16.107 + { 16.108 + case 16: 16.109 + { 16.110 + for (int y = 0; y < 144; y++) 16.111 + { 16.112 + int yLine = (y + gbBorderRowSkip + 1) * (gbBorderLineSkip + 2) + 16.113 + gbBorderColumnSkip; 16.114 + u16 *dest = (u16 *)pix + yLine; 16.115 + for (register int x = 0; x < 160; x++) 16.116 + gbSgbDraw16Bit(dest++, color); 16.117 + } 16.118 + } 16.119 + break; 16.120 + case 24: 16.121 + { 16.122 + for (int y = 0; y < 144; y++) 16.123 + { 16.124 + int yLine = (y + gbBorderRowSkip) * gbBorderLineSkip + gbBorderColumnSkip; 16.125 + u8 *dest = (u8 *)pix + yLine * 3; 16.126 + for (register int x = 0; x < 160; x++) 16.127 + { 16.128 + gbSgbDraw24Bit(dest, color); 16.129 + dest += 3; 16.130 + } 16.131 + } 16.132 + } 16.133 + break; 16.134 + case 32: 16.135 + { 16.136 + for (int y = 0; y < 144; y++) 16.137 + { 16.138 + int yLine = (y + gbBorderRowSkip + 1) * (gbBorderLineSkip + 1) + gbBorderColumnSkip; 16.139 + u32 *dest = (u32 *)pix + yLine; 16.140 + for (register int x = 0; x < 160; x++) 16.141 + { 16.142 + gbSgbDraw32Bit(dest++, color); 16.143 + } 16.144 + } 16.145 + } 16.146 + break; 16.147 + } 16.148 +} 16.149 + 16.150 +void gbSgbRenderScreenToBuffer() 16.151 +{ 16.152 + u16 mapAddress = 0x9800; 16.153 + 16.154 + if (register_LCDC & 0x08) 16.155 + mapAddress = 0x9c00; 16.156 + 16.157 + u16 patternAddress = 0x8800; 16.158 + 16.159 + int flag = 1; 16.160 + 16.161 + if (register_LCDC & 0x10) 16.162 + { 16.163 + patternAddress = 0x8000; 16.164 + flag = 0; 16.165 + } 16.166 + 16.167 + u8 *toAddress = gbSgbScreenBuffer; 16.168 + 16.169 + for (int i = 0; i < 13; i++) 16.170 + { 16.171 + for (int j = 0; j < 20; j++) 16.172 + { 16.173 + int tile = gbReadMemoryQuick(mapAddress); 16.174 + mapAddress++; 16.175 + 16.176 + if (flag) 16.177 + { 16.178 + if (tile > 127) 16.179 + tile -= 128; 16.180 + else 16.181 + tile += 128; 16.182 + } 16.183 + for (int k = 0; k < 16; k++) 16.184 + *toAddress++ = gbReadMemoryQuick(patternAddress + tile * 16 + k); 16.185 + } 16.186 + mapAddress += 12; 16.187 + } 16.188 +} 16.189 + 16.190 +void gbSgbDrawBorderTile(int x, int y, int tile, int attr) 16.191 +{ 16.192 + u16 *dest = (u16 *)pix + ((y + 1) * (256 + 2)) + x; 16.193 + u8 * dest8 = (u8 *)pix + ((y * 256) + x) * 3; 16.194 + u32 *dest32 = (u32 *)pix + ((y + 1) * 257) + x; 16.195 + 16.196 + u8 *tileAddress = &gbSgbBorderChar[tile * 32]; 16.197 + u8 *tileAddress2 = &gbSgbBorderChar[tile * 32 + 16]; 16.198 + 16.199 + u8 l = 8; 16.200 + 16.201 + u8 palette = ((attr >> 2) & 7); 16.202 + 16.203 + if (palette < 4) 16.204 + palette += 4; 16.205 + 16.206 + palette *= 16; 16.207 + 16.208 + u8 xx = 0; 16.209 + u8 yy = 0; 16.210 + 16.211 + int flipX = attr & 0x40; 16.212 + int flipY = attr & 0x80; 16.213 + 16.214 + while (l > 0) 16.215 + { 16.216 + u8 mask = 0x80; 16.217 + u8 a = *tileAddress++; 16.218 + u8 b = *tileAddress++; 16.219 + u8 c = *tileAddress2++; 16.220 + u8 d = *tileAddress2++; 16.221 + 16.222 + while (mask > 0) 16.223 + { 16.224 + u8 color = 0; 16.225 + if (a & mask) 16.226 + color++; 16.227 + if (b & mask) 16.228 + color += 2; 16.229 + if (c & mask) 16.230 + color += 4; 16.231 + if (d & mask) 16.232 + color += 8; 16.233 + 16.234 + u8 xxx = xx; 16.235 + u8 yyy = yy; 16.236 + 16.237 + if (flipX) 16.238 + xxx = 7 - xx; 16.239 + if (flipY) 16.240 + yyy = 7 - yy; 16.241 + 16.242 + u8 realx = x + xxx; 16.243 + u8 realy = y + yyy; 16.244 + 16.245 + u16 c = gbPalette[palette + color]; 16.246 + if (!color) 16.247 + c = gbPalette[0]; 16.248 + if ((realy < 40 || realy >= 184) || (realx < 48 || realx >= 208)) 16.249 + { 16.250 + switch (systemColorDepth) 16.251 + { 16.252 + case 16: 16.253 + gbSgbDraw16Bit(dest + yyy * (256 + 2) + xxx, c); 16.254 + break; 16.255 + case 24: 16.256 + gbSgbDraw24Bit(dest8 + (yyy * 256 + xxx) * 3, c); 16.257 + break; 16.258 + case 32: 16.259 + gbSgbDraw32Bit(dest32 + yyy * (256 + 1) + xxx, c); 16.260 + break; 16.261 + } 16.262 + } 16.263 + 16.264 + mask >>= 1; 16.265 + 16.266 + xx++; 16.267 + } 16.268 + yy++; 16.269 + xx = 0; 16.270 + l--; 16.271 + mask = 0x80; 16.272 + } 16.273 +} 16.274 + 16.275 +void gbSgbRenderBorder() 16.276 +{ 16.277 + if (gbBorderOn) 16.278 + { 16.279 + u8 *fromAddress = gbSgbBorder; 16.280 + 16.281 + for (u8 y = 0; y < 28; y++) 16.282 + { 16.283 + for (u8 x = 0; x < 32; x++) 16.284 + { 16.285 + u8 tile = *fromAddress++; 16.286 + u8 attr = *fromAddress++; 16.287 + 16.288 + gbSgbDrawBorderTile(x * 8, y * 8, tile, attr); 16.289 + } 16.290 + } 16.291 + } 16.292 +} 16.293 + 16.294 +void gbSgbPicture() 16.295 +{ 16.296 + gbSgbRenderScreenToBuffer(); 16.297 + 16.298 + memcpy(gbSgbBorder, gbSgbScreenBuffer, 2048); 16.299 + 16.300 + u16 *paletteAddr = (u16 *)&gbSgbScreenBuffer[2048]; 16.301 + 16.302 + for (int i = 64; i < 128; i++) 16.303 + { 16.304 + gbPalette[i] = READ16LE(paletteAddr++); 16.305 + } 16.306 + 16.307 + gbSgbCGBSupport |= 4; 16.308 + 16.309 + if (gbBorderAutomatic && !gbBorderOn && gbSgbCGBSupport > 4) 16.310 + { 16.311 + gbBorderOn = 1; 16.312 + systemGbBorderOn(); 16.313 + } 16.314 + 16.315 + if (gbBorderOn && !gbSgbMask) 16.316 + gbSgbRenderBorder(); 16.317 + 16.318 + if (gbSgbMode && gbCgbMode && gbSgbCGBSupport > 4) 16.319 + { 16.320 + gbSgbCGBSupport = 0; 16.321 + gbSgbMode = 2; 16.322 + gbSgbMask = 0; 16.323 + gbSgbRenderBorder(); 16.324 + gbReset(); 16.325 + } 16.326 + 16.327 + if (gbSgbCGBSupport > 4) 16.328 + gbSgbCGBSupport = 0; 16.329 +} 16.330 + 16.331 +void gbSgbSetPalette(int a, int b, u16 *p) 16.332 +{ 16.333 + u16 bit00 = READ16LE(p++); 16.334 + int i; 16.335 + 16.336 + for (i = 1; i < 4; i++) 16.337 + { 16.338 + gbPalette[a * 4 + i] = READ16LE(p++); 16.339 + } 16.340 + 16.341 + for (i = 1; i < 4; i++) 16.342 + { 16.343 + gbPalette[b * 4 + i] = READ16LE(p++); 16.344 + } 16.345 + 16.346 + gbPalette[0] = gbPalette[4] = gbPalette[8] = gbPalette[12] = bit00; 16.347 + if (gbBorderOn && !gbSgbMask) 16.348 + gbSgbRenderBorder(); 16.349 +} 16.350 + 16.351 +void gbSgbScpPalette() 16.352 +{ 16.353 + gbSgbRenderScreenToBuffer(); 16.354 + 16.355 + u16 *fromAddress = (u16 *)gbSgbScreenBuffer; 16.356 + 16.357 + for (int i = 0; i < 512 * 4; i++) 16.358 + { 16.359 + gbSgbSCPPalette[i] = READ16LE(fromAddress++); 16.360 + } 16.361 +} 16.362 + 16.363 +void gbSgbSetATF(int n) 16.364 +{ 16.365 + if (n < 0) 16.366 + n = 0; 16.367 + if (n > 44) 16.368 + n = 44; 16.369 + memcpy(gbSgbATF, &gbSgbATFList[n * 20 * 18], 20 * 18); 16.370 + 16.371 + if (gbSgbPacket[1] & 0x40) 16.372 + { 16.373 + gbSgbMask = 0; 16.374 + if (gbBorderOn) 16.375 + gbSgbRenderBorder(); 16.376 + } 16.377 +} 16.378 + 16.379 +void gbSgbSetPalette() 16.380 +{ 16.381 + u16 pal = READ16LE((((u16 *)&gbSgbPacket[1]))) & 511; 16.382 + memcpy(&gbPalette[0], &gbSgbSCPPalette[pal * 4], 4 * sizeof(u16)); 16.383 + 16.384 + pal = READ16LE((((u16 *)&gbSgbPacket[3]))) & 511; 16.385 + memcpy(&gbPalette[4], &gbSgbSCPPalette[pal * 4], 4 * sizeof(u16)); 16.386 + 16.387 + pal = READ16LE((((u16 *)&gbSgbPacket[5]))) & 511; 16.388 + memcpy(&gbPalette[8], &gbSgbSCPPalette[pal * 4], 4 * sizeof(u16)); 16.389 + 16.390 + pal = READ16LE((((u16 *)&gbSgbPacket[7]))) & 511; 16.391 + memcpy(&gbPalette[12], &gbSgbSCPPalette[pal * 4], 4 * sizeof(u16)); 16.392 + 16.393 + u8 atf = gbSgbPacket[9]; 16.394 + 16.395 + if (atf & 0x80) 16.396 + { 16.397 + gbSgbSetATF(atf & 0x3f); 16.398 + } 16.399 + 16.400 + if (atf & 0x40) 16.401 + { 16.402 + gbSgbMask = 0; 16.403 + if (gbBorderOn) 16.404 + gbSgbRenderBorder(); 16.405 + } 16.406 +} 16.407 + 16.408 +void gbSgbAttributeBlock() 16.409 +{ 16.410 + u8 *fromAddress = &gbSgbPacket[1]; 16.411 + 16.412 + u8 nDataSet = *fromAddress++; 16.413 + if (nDataSet > 12) 16.414 + nDataSet = 12; 16.415 + if (nDataSet == 0) 16.416 + nDataSet = 1; 16.417 + 16.418 + while (nDataSet) 16.419 + { 16.420 + u8 controlCode = (*fromAddress++) & 7; 16.421 + u8 paletteDesignation = (*fromAddress++) & 0x3f; 16.422 + u8 startH = (*fromAddress++) & 0x1f; 16.423 + u8 startV = (*fromAddress++) & 0x1f; 16.424 + u8 endH = (*fromAddress++) & 0x1f; 16.425 + u8 endV = (*fromAddress++) & 0x1f; 16.426 + 16.427 + u8 *toAddress = gbSgbATF; 16.428 + 16.429 + for (u8 y = 0; y < 18; y++) 16.430 + { 16.431 + for (u8 x = 0; x < 20; x++) 16.432 + { 16.433 + if (x < startH || y < startV || 16.434 + x > endH || y > endV) 16.435 + { 16.436 + // outside 16.437 + if (controlCode & 0x04) 16.438 + *toAddress = (paletteDesignation >> 4) & 0x03; 16.439 + } 16.440 + else if (x > startH && x < endH && 16.441 + y > startV && y < endV) 16.442 + { 16.443 + // inside 16.444 + if (controlCode & 0x01) 16.445 + *toAddress = paletteDesignation & 0x03; 16.446 + } 16.447 + else 16.448 + { 16.449 + // surrounding line 16.450 + if (controlCode & 0x02) 16.451 + *toAddress = (paletteDesignation >> 2) & 0x03; 16.452 + else if (controlCode == 0x01) 16.453 + *toAddress = paletteDesignation & 0x03; 16.454 + } 16.455 + toAddress++; 16.456 + } 16.457 + } 16.458 + nDataSet--; 16.459 + } 16.460 +} 16.461 + 16.462 +void gbSgbSetColumnPalette(u8 col, u8 p) 16.463 +{ 16.464 + // if(col < 0) 16.465 + // col = 0; 16.466 + if (col > 19) 16.467 + col = 19; 16.468 + 16.469 + p &= 3; 16.470 + 16.471 + u8 *toAddress = &gbSgbATF[col]; 16.472 + 16.473 + for (u8 y = 0; y < 18; y++) 16.474 + { 16.475 + *toAddress = p; 16.476 + toAddress += 20; 16.477 + } 16.478 +} 16.479 + 16.480 +void gbSgbSetRowPalette(u8 row, u8 p) 16.481 +{ 16.482 + // if(row < 0) 16.483 + // row = 0; 16.484 + if (row > 17) 16.485 + row = 17; 16.486 + 16.487 + p &= 3; 16.488 + 16.489 + u8 *toAddress = &gbSgbATF[row * 20]; 16.490 + 16.491 + for (u8 x = 0; x < 20; x++) 16.492 + { 16.493 + *toAddress++ = p; 16.494 + } 16.495 +} 16.496 + 16.497 +void gbSgbAttributeDivide() 16.498 +{ 16.499 + u8 control = gbSgbPacket[1]; 16.500 + u8 coord = gbSgbPacket[2]; 16.501 + u8 colorBR = control & 3; 16.502 + u8 colorAL = (control >> 2) & 3; 16.503 + u8 colorOL = (control >> 4) & 3; 16.504 + 16.505 + if (control & 0x40) 16.506 + { 16.507 + if (coord > 17) 16.508 + coord = 17; 16.509 + 16.510 + for (u8 i = 0; i < 18; i++) 16.511 + { 16.512 + if (i < coord) 16.513 + gbSgbSetRowPalette(i, colorAL); 16.514 + else if (i > coord) 16.515 + gbSgbSetRowPalette(i, colorBR); 16.516 + else 16.517 + gbSgbSetRowPalette(i, colorOL); 16.518 + } 16.519 + } 16.520 + else 16.521 + { 16.522 + if (coord > 19) 16.523 + coord = 19; 16.524 + 16.525 + for (u8 i = 0; i < 20; i++) 16.526 + { 16.527 + if (i < coord) 16.528 + gbSgbSetColumnPalette(i, colorAL); 16.529 + else if (i > coord) 16.530 + gbSgbSetColumnPalette(i, colorBR); 16.531 + else 16.532 + gbSgbSetColumnPalette(i, colorOL); 16.533 + } 16.534 + } 16.535 +} 16.536 + 16.537 +void gbSgbAttributeLine() 16.538 +{ 16.539 + u8 *fromAddress = &gbSgbPacket[1]; 16.540 + 16.541 + u8 nDataSet = *fromAddress++; 16.542 + 16.543 + if (nDataSet > 0x6e) 16.544 + nDataSet = 0x6e; 16.545 + 16.546 + while (nDataSet) 16.547 + { 16.548 + u8 line = *fromAddress++; 16.549 + u8 num = line & 0x1f; 16.550 + u8 pal = (line >> 5) & 0x03; 16.551 + if (line & 0x80) 16.552 + { 16.553 + if (num > 17) 16.554 + num = 17; 16.555 + gbSgbSetRowPalette(num, pal); 16.556 + } 16.557 + else 16.558 + { 16.559 + if (num > 19) 16.560 + num = 19; 16.561 + gbSgbSetColumnPalette(num, pal); 16.562 + } 16.563 + nDataSet--; 16.564 + } 16.565 +} 16.566 + 16.567 +void gbSgbAttributeCharacter() 16.568 +{ 16.569 + u8 startH = gbSgbPacket[1] & 0x1f; 16.570 + u8 startV = gbSgbPacket[2] & 0x1f; 16.571 + int nDataSet = READ16LE(((u16 *)&gbSgbPacket[3])); 16.572 + int style = gbSgbPacket[5] & 1; 16.573 + if (startH > 19) 16.574 + startH = 19; 16.575 + if (startV > 17) 16.576 + startV = 17; 16.577 + 16.578 + u8 s = 6; 16.579 + u8 *fromAddress = &gbSgbPacket[6]; 16.580 + u8 v = *fromAddress++; 16.581 + 16.582 + if (style) 16.583 + { 16.584 + while (nDataSet) 16.585 + { 16.586 + u8 p = (v >> s) & 3; 16.587 + gbSgbATF[startV * 20 + startH] = p; 16.588 + startV++; 16.589 + if (startV == 18) 16.590 + { 16.591 + startV = 0; 16.592 + startH++; 16.593 + if (startH == 20) 16.594 + break; 16.595 + } 16.596 + 16.597 + if (s) 16.598 + s -= 2; 16.599 + else 16.600 + { 16.601 + s = 6; 16.602 + v = *fromAddress++; 16.603 + nDataSet--; 16.604 + } 16.605 + } 16.606 + } 16.607 + else 16.608 + { 16.609 + while (nDataSet) 16.610 + { 16.611 + u8 p = (v >> s) & 3; 16.612 + gbSgbATF[startV * 20 + startH] = p; 16.613 + startH++; 16.614 + if (startH == 20) 16.615 + { 16.616 + startH = 0; 16.617 + startV++; 16.618 + if (startV == 18) 16.619 + break; 16.620 + } 16.621 + 16.622 + if (s) 16.623 + s -= 2; 16.624 + else 16.625 + { 16.626 + s = 6; 16.627 + v = *fromAddress++; 16.628 + nDataSet--; 16.629 + } 16.630 + } 16.631 + } 16.632 +} 16.633 + 16.634 +void gbSgbSetATFList() 16.635 +{ 16.636 + gbSgbRenderScreenToBuffer(); 16.637 + 16.638 + u8 *fromAddress = gbSgbScreenBuffer; 16.639 + u8 *toAddress = gbSgbATFList; 16.640 + 16.641 + for (int i = 0; i < 45; i++) 16.642 + { 16.643 + for (int j = 0; j < 90; j++) 16.644 + { 16.645 + u8 v = *fromAddress++; 16.646 + u8 s = 6; 16.647 + if (i == 2) 16.648 + s = 6; 16.649 + for (int k = 0; k < 4; k++) 16.650 + { 16.651 + *toAddress++ = (v >> s) & 0x03; 16.652 + s -= 2; 16.653 + } 16.654 + } 16.655 + } 16.656 +} 16.657 + 16.658 +void gbSgbMaskEnable() 16.659 +{ 16.660 + int gbSgbMaskFlag = gbSgbPacket[1] & 3; 16.661 + 16.662 + gbSgbMask = gbSgbMaskFlag; 16.663 + 16.664 + switch (gbSgbMaskFlag) 16.665 + { 16.666 + case 1: 16.667 + break; 16.668 + case 2: 16.669 + gbSgbFillScreen(0x0000); 16.670 + // memset(&gbPalette[0], 0, 128*sizeof(u16)); 16.671 + break; 16.672 + case 3: 16.673 + gbSgbFillScreen(gbPalette[0]); 16.674 + break; 16.675 + } 16.676 + if (!gbSgbMask) 16.677 + { 16.678 + if (gbBorderOn) 16.679 + gbSgbRenderBorder(); 16.680 + } 16.681 +} 16.682 + 16.683 +void gbSgbChrTransfer() 16.684 +{ 16.685 + gbSgbRenderScreenToBuffer(); 16.686 + 16.687 + int address = (gbSgbPacket[1] & 1) * (128 * 32); 16.688 + 16.689 + if (gbSgbPacket[1] & 1) 16.690 + gbSgbCGBSupport |= 2; 16.691 + else 16.692 + gbSgbCGBSupport |= 1; 16.693 + 16.694 + memcpy(&gbSgbBorderChar[address], gbSgbScreenBuffer, 128 * 32); 16.695 + 16.696 + if (gbBorderAutomatic && !gbBorderOn && gbSgbCGBSupport > 4) 16.697 + { 16.698 + gbBorderOn = 1; 16.699 + systemGbBorderOn(); 16.700 + } 16.701 + 16.702 + if (gbBorderOn && !gbSgbMask) 16.703 + gbSgbRenderBorder(); 16.704 + 16.705 + if (gbSgbMode && gbCgbMode && gbSgbCGBSupport == 7) 16.706 + { 16.707 + gbSgbCGBSupport = 0; 16.708 + gbSgbMode = 2; 16.709 + gbSgbMask = 0; 16.710 + gbSgbRenderBorder(); 16.711 + gbReset(); 16.712 + } 16.713 + 16.714 + if (gbSgbCGBSupport > 4) 16.715 + gbSgbCGBSupport = 0; 16.716 +} 16.717 + 16.718 +void gbSgbMultiRequest() 16.719 +{ 16.720 + if (gbSgbPacket[1] & 1) 16.721 + { 16.722 + gbSgbMultiplayer = 1; 16.723 + if (gbSgbPacket[1] & 2) 16.724 + gbSgbFourPlayers = 1; 16.725 + else 16.726 + gbSgbFourPlayers = 0; 16.727 + gbSgbNextController = 0x0e; 16.728 + } 16.729 + else 16.730 + { 16.731 + gbSgbFourPlayers = 0; 16.732 + gbSgbMultiplayer = 0; 16.733 + gbSgbNextController = 0x0f; 16.734 + } 16.735 +} 16.736 + 16.737 +void gbSgbCommand() 16.738 +{ 16.739 + int command = gbSgbPacket[0] >> 3; 16.740 + // int nPacket = gbSgbPacket[0] & 7; 16.741 + 16.742 + switch (command) 16.743 + { 16.744 + case 0x00: 16.745 + gbSgbSetPalette(0, 1, (u16 *)&gbSgbPacket[1]); 16.746 + break; 16.747 + case 0x01: 16.748 + gbSgbSetPalette(2, 3, (u16 *)&gbSgbPacket[1]); 16.749 + break; 16.750 + case 0x02: 16.751 + gbSgbSetPalette(0, 3, (u16 *)&gbSgbPacket[1]); 16.752 + break; 16.753 + case 0x03: 16.754 + gbSgbSetPalette(1, 2, (u16 *)&gbSgbPacket[1]); 16.755 + break; 16.756 + case 0x04: 16.757 + gbSgbAttributeBlock(); 16.758 + break; 16.759 + case 0x05: 16.760 + gbSgbAttributeLine(); 16.761 + break; 16.762 + case 0x06: 16.763 + gbSgbAttributeDivide(); 16.764 + break; 16.765 + case 0x07: 16.766 + gbSgbAttributeCharacter(); 16.767 + break; 16.768 + case 0x0a: 16.769 + gbSgbSetPalette(); 16.770 + break; 16.771 + case 0x0b: 16.772 + gbSgbScpPalette(); 16.773 + break; 16.774 + case 0x11: 16.775 + gbSgbMultiRequest(); 16.776 + break; 16.777 + case 0x13: 16.778 + gbSgbChrTransfer(); 16.779 + break; 16.780 + case 0x14: 16.781 + gbSgbPicture(); 16.782 + break; 16.783 + case 0x15: 16.784 + gbSgbSetATFList(); 16.785 + break; 16.786 + case 0x16: 16.787 + gbSgbSetATF(gbSgbPacket[1] & 0x3f); 16.788 + break; 16.789 + case 0x17: 16.790 + gbSgbMaskEnable(); 16.791 + break; 16.792 + } 16.793 +} 16.794 + 16.795 +void gbSgbResetPacketState() 16.796 +{ 16.797 + gbSgbPacketState = GBSGB_NONE; 16.798 + gbSgbPacketTimeout = 0; 16.799 +} 16.800 + 16.801 +void gbSgbDoBitTransfer(u8 value) 16.802 +{ 16.803 + value = value & 0x30; 16.804 + switch (gbSgbPacketState) 16.805 + { 16.806 + case GBSGB_NONE: 16.807 + if (value == 0) 16.808 + { 16.809 + gbSgbPacketState = GBSGB_RESET; 16.810 + gbSgbPacketTimeout = GBSGB_PACKET_TIMEOUT; 16.811 + } 16.812 + else if (value == 0x30) 16.813 + { 16.814 + if (gbSgbMultiplayer) 16.815 + { 16.816 + if ((gbSgbReadingController & 7) == 7) 16.817 + { 16.818 + gbSgbReadingController = 0; 16.819 + if (gbSgbMultiplayer) 16.820 + { 16.821 + gbSgbNextController--; 16.822 + if (gbSgbFourPlayers) 16.823 + { 16.824 + if (gbSgbNextController == 0x0b) 16.825 + gbSgbNextController = 0x0f; 16.826 + } 16.827 + else 16.828 + { 16.829 + if (gbSgbNextController == 0x0d) 16.830 + gbSgbNextController = 0x0f; 16.831 + } 16.832 + } 16.833 + } 16.834 + else 16.835 + { 16.836 + gbSgbReadingController &= 3; 16.837 + } 16.838 + } 16.839 + gbSgbPacketTimeout = 0; 16.840 + } 16.841 + else 16.842 + { 16.843 + if (value == 0x10) 16.844 + gbSgbReadingController |= 0x2; 16.845 + else if (value == 0x20) 16.846 + gbSgbReadingController |= 0x01; 16.847 + gbSgbPacketTimeout = 0; 16.848 + } 16.849 + gbSgbPacketTimeout = 0; 16.850 + break; 16.851 + case GBSGB_RESET: 16.852 + if (value == 0x30) 16.853 + { 16.854 + gbSgbPacketState = GBSGB_PACKET_TRANSMIT; 16.855 + gbSgbPacketByte = 0; 16.856 + gbSgbPacketNBits = 0; 16.857 + gbSgbPacketTimeout = GBSGB_PACKET_TIMEOUT; 16.858 + } 16.859 + else if (value == 0x00) 16.860 + { 16.861 + gbSgbPacketTimeout = GBSGB_PACKET_TIMEOUT; 16.862 + gbSgbPacketState = GBSGB_RESET; 16.863 + } 16.864 + else 16.865 + { 16.866 + gbSgbPacketState = GBSGB_NONE; 16.867 + gbSgbPacketTimeout = 0; 16.868 + } 16.869 + break; 16.870 + case GBSGB_PACKET_TRANSMIT: 16.871 + if (value == 0) 16.872 + { 16.873 + gbSgbPacketState = GBSGB_RESET; 16.874 + gbSgbPacketTimeout = 0; 16.875 + } 16.876 + else if (value == 0x30) 16.877 + { 16.878 + if (gbSgbPacketNBits == 128) 16.879 + { 16.880 + gbSgbPacketNBits = 0; 16.881 + gbSgbPacketByte = 0; 16.882 + gbSgbPacketNumber++; 16.883 + gbSgbPacketTimeout = 0; 16.884 + if (gbSgbPacketNumber == (gbSgbPacket[0] & 7)) 16.885 + { 16.886 + gbSgbCommand(); 16.887 + gbSgbPacketNumber = 0; 16.888 + gbSgbPacketState = GBSGB_NONE; 16.889 + gbSgbPacketTimeout = 0; 16.890 + } 16.891 + } 16.892 + else 16.893 + { 16.894 + if (gbSgbPacketNBits < 128) 16.895 + { 16.896 + gbSgbPacket[gbSgbPacketNumber * 16 + gbSgbPacketByte] >>= 1; 16.897 + gbSgbPacket[gbSgbPacketNumber * 16 + gbSgbPacketByte] |= gbSgbBit; 16.898 + gbSgbPacketNBits++; 16.899 + if (!(gbSgbPacketNBits & 7)) 16.900 + { 16.901 + gbSgbPacketByte++; 16.902 + } 16.903 + gbSgbPacketTimeout = GBSGB_PACKET_TIMEOUT; 16.904 + } 16.905 + } 16.906 + } 16.907 + else 16.908 + { 16.909 + if (value == 0x20) 16.910 + gbSgbBit = 0x00; 16.911 + else 16.912 + gbSgbBit = 0x80; 16.913 + gbSgbPacketTimeout = GBSGB_PACKET_TIMEOUT; 16.914 + } 16.915 + gbSgbReadingController = 0; 16.916 + break; 16.917 + default: 16.918 + gbSgbPacketState = GBSGB_NONE; 16.919 + gbSgbPacketTimeout = 0; 16.920 + break; 16.921 + } 16.922 +} 16.923 + 16.924 +variable_desc gbSgbSaveStruct[] = { 16.925 + { &gbSgbMask, sizeof(int32) }, 16.926 + { &gbSgbPacketState, sizeof(int32) }, 16.927 + { &gbSgbBit, sizeof(int32) }, 16.928 + { &gbSgbPacketNBits, sizeof(int32) }, 16.929 + { &gbSgbPacketByte, sizeof(int32) }, 16.930 + { &gbSgbPacketNumber, sizeof(int32) }, 16.931 + { &gbSgbMultiplayer, sizeof(int32) }, 16.932 + { &gbSgbNextController, sizeof(u8) }, 16.933 + { &gbSgbReadingController, sizeof(u8) }, 16.934 + { NULL, 0 } 16.935 +}; 16.936 + 16.937 +variable_desc gbSgbSaveStructV3[] = { 16.938 + { &gbSgbMask, sizeof(int32) }, 16.939 + { &gbSgbPacketState, sizeof(int32) }, 16.940 + { &gbSgbBit, sizeof(int32) }, 16.941 + { &gbSgbPacketNBits, sizeof(int32) }, 16.942 + { &gbSgbPacketByte, sizeof(int32) }, 16.943 + { &gbSgbPacketNumber, sizeof(int32) }, 16.944 + { &gbSgbMultiplayer, sizeof(int32) }, 16.945 + { &gbSgbNextController, sizeof(u8) }, 16.946 + { &gbSgbReadingController, sizeof(u8) }, 16.947 + { &gbSgbFourPlayers, sizeof(int32) }, 16.948 + { NULL, 0 } 16.949 +}; 16.950 + 16.951 +void gbSgbSaveGame(gzFile gzFile) 16.952 +{ 16.953 + utilWriteData(gzFile, gbSgbSaveStructV3); 16.954 + 16.955 + utilGzWrite(gzFile, gbSgbBorder, 2048); 16.956 + utilGzWrite(gzFile, gbSgbBorderChar, 32 * 256); 16.957 + 16.958 + utilGzWrite(gzFile, gbSgbPacket, 16 * 7); 16.959 + 16.960 + utilGzWrite(gzFile, gbSgbSCPPalette, 4 * 512 * sizeof(u16)); 16.961 + utilGzWrite(gzFile, gbSgbATF, 20 * 18); 16.962 + utilGzWrite(gzFile, gbSgbATFList, 45 * 20 * 18); 16.963 + 16.964 + utilGzWrite(gzFile, gbSgbScreenBuffer, 4160); 16.965 + utilGzWrite(gzFile, &gbSgbMode, sizeof(gbSgbMode)); 16.966 + utilGzWrite(gzFile, &gbSgbCGBSupport, sizeof(gbSgbCGBSupport)); 16.967 + utilGzWrite(gzFile, &gbSgbPacketTimeout, sizeof(gbSgbPacketTimeout)); 16.968 +} 16.969 + 16.970 +void gbSgbReadGame(gzFile gzFile, int version) 16.971 +{ 16.972 + if (version >= 3) 16.973 + utilReadData(gzFile, gbSgbSaveStructV3); 16.974 + else 16.975 + { 16.976 + utilReadData(gzFile, gbSgbSaveStruct); 16.977 + gbSgbFourPlayers = 0; 16.978 + } 16.979 + 16.980 + if (version >= 8) 16.981 + { 16.982 + utilGzRead(gzFile, gbSgbBorder, 2048); 16.983 + utilGzRead(gzFile, gbSgbBorderChar, 32 * 256); 16.984 + } 16.985 + 16.986 + utilGzRead(gzFile, gbSgbPacket, 16 * 7); 16.987 + 16.988 + utilGzRead(gzFile, gbSgbSCPPalette, 4 * 512 * sizeof(u16)); 16.989 + utilGzRead(gzFile, gbSgbATF, 20 * 18); 16.990 + utilGzRead(gzFile, gbSgbATFList, 45 * 20 * 18); 16.991 + 16.992 + if (version >= 11) 16.993 + { 16.994 + utilGzRead(gzFile, gbSgbScreenBuffer, 4160); 16.995 + utilGzRead(gzFile, &gbSgbMode, sizeof(gbSgbMode)); 16.996 + utilGzRead(gzFile, &gbSgbCGBSupport, sizeof(gbSgbCGBSupport)); 16.997 + utilGzRead(gzFile, &gbSgbPacketTimeout, sizeof(gbSgbPacketTimeout)); 16.998 + } 16.999 +} 16.1000 +
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 17.2 +++ b/src/gb/gbSGB.h Sat Mar 03 11:44:47 2012 -0600 17.3 @@ -0,0 +1,30 @@ 17.4 +#ifndef VBA_GB_SGB_H 17.5 +#define VBA_GB_SGB_H 17.6 + 17.7 +#if _MSC_VER > 1000 17.8 +#pragma once 17.9 +#endif // _MSC_VER > 1000 17.10 + 17.11 +#include "zlib.h" 17.12 +#include "../Port.h" 17.13 + 17.14 +void gbSgbInit(); 17.15 +void gbSgbShutdown(); 17.16 +void gbSgbCommand(); 17.17 +void gbSgbResetPacketState(); 17.18 +void gbSgbReset(); 17.19 +void gbSgbDoBitTransfer(u8); 17.20 +void gbSgbSaveGame(gzFile); 17.21 +void gbSgbReadGame(gzFile, int version); 17.22 +void gbSgbRenderBorder(); 17.23 + 17.24 +extern u8 gbSgbATF[20*18]; 17.25 +extern int32 gbSgbMode; 17.26 +extern int32 gbSgbMask; 17.27 +extern int32 gbSgbMultiplayer; 17.28 +extern u8 gbSgbNextController; 17.29 +extern int32 gbSgbPacketTimeout; 17.30 +extern u8 gbSgbReadingController; 17.31 +extern int32 gbSgbFourPlayers; 17.32 + 17.33 +#endif // VBA_GB_SGB_H
18.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 18.2 +++ b/src/gb/gbSound.cpp Sat Mar 03 11:44:47 2012 -0600 18.3 @@ -0,0 +1,1139 @@ 18.4 +#ifdef WIN32 18.5 +# include "../win32/stdafx.h" 18.6 +# include "../win32/VBA.h" 18.7 +#endif 18.8 + 18.9 +#include <cstring> 18.10 +#include <cassert> 18.11 + 18.12 +#include "../common/System.h" 18.13 +#include "../common/Util.h" 18.14 +//#include "../Blip_Buffer.h" 18.15 +#include "gbGlobals.h" 18.16 +#include "gbSound.h" 18.17 + 18.18 +#ifndef countof 18.19 +#define countof(a) (sizeof(a) / sizeof(a[0])) 18.20 +#endif 18.21 + 18.22 +extern u8 soundBuffer[6][735]; 18.23 +extern u16 soundFinalWave[1470]; 18.24 +extern u16 soundFrameSound[735 * 30 * 2]; 18.25 +extern int32 soundVolume; 18.26 + 18.27 +soundtick_t GB_USE_TICKS_AS = 24; // (1048576.0/44100.0); // FIXME: (4194304.0/70224.0)(fps) vs 60.0fps? 18.28 + 18.29 +#define SOUND_MAGIC 0x60000000 18.30 +#define SOUND_MAGIC_2 0x30000000 18.31 +#define NOISE_MAGIC (2097152.0 / 44100.0) 18.32 + 18.33 +extern int32 speed; 18.34 + 18.35 +extern u8 soundWavePattern[4][32]; 18.36 + 18.37 +extern u32 soundBufferLen; 18.38 +extern u32 soundBufferTotalLen; 18.39 +extern int32 soundQuality; 18.40 +extern int32 soundPaused; 18.41 +extern int32 soundPlay; 18.42 +extern soundtick_t soundTicks; 18.43 +extern soundtick_t SOUND_CLOCK_TICKS; 18.44 +extern u32 soundNextPosition; 18.45 + 18.46 +extern int32 soundLevel1; 18.47 +extern int32 soundLevel2; 18.48 +extern int32 soundBalance; 18.49 +extern int32 soundMasterOn; 18.50 +extern u32 soundIndex; 18.51 +extern u32 soundBufferIndex; 18.52 +extern int32 soundFrameSoundWritten; 18.53 +int32 soundVIN = 0; 18.54 +extern int32 soundDebug; 18.55 + 18.56 +extern int32 sound1On; 18.57 +extern int32 sound1ATL; 18.58 +extern int32 sound1Skip; 18.59 +extern int32 sound1Index; 18.60 +extern int32 sound1Continue; 18.61 +extern int32 sound1EnvelopeVolume; 18.62 +extern int32 sound1EnvelopeATL; 18.63 +extern int32 sound1EnvelopeUpDown; 18.64 +extern int32 sound1EnvelopeATLReload; 18.65 +extern int32 sound1SweepATL; 18.66 +extern int32 sound1SweepATLReload; 18.67 +extern int32 sound1SweepSteps; 18.68 +extern int32 sound1SweepUpDown; 18.69 +extern int32 sound1SweepStep; 18.70 +extern u8 * sound1Wave; 18.71 + 18.72 +extern int32 sound2On; 18.73 +extern int32 sound2ATL; 18.74 +extern int32 sound2Skip; 18.75 +extern int32 sound2Index; 18.76 +extern int32 sound2Continue; 18.77 +extern int32 sound2EnvelopeVolume; 18.78 +extern int32 sound2EnvelopeATL; 18.79 +extern int32 sound2EnvelopeUpDown; 18.80 +extern int32 sound2EnvelopeATLReload; 18.81 +extern u8 * sound2Wave; 18.82 + 18.83 +extern int32 sound3On; 18.84 +extern int32 sound3ATL; 18.85 +extern int32 sound3Skip; 18.86 +extern int32 sound3Index; 18.87 +extern int32 sound3Continue; 18.88 +extern int32 sound3OutputLevel; 18.89 +extern int32 sound3Last; 18.90 + 18.91 +extern int32 sound4On; 18.92 +extern int32 sound4Clock; 18.93 +extern int32 sound4ATL; 18.94 +extern int32 sound4Skip; 18.95 +extern int32 sound4Index; 18.96 +extern int32 sound4ShiftRight; 18.97 +extern int32 sound4ShiftSkip; 18.98 +extern int32 sound4ShiftIndex; 18.99 +extern int32 sound4NSteps; 18.100 +extern int32 sound4CountDown; 18.101 +extern int32 sound4Continue; 18.102 +extern int32 sound4EnvelopeVolume; 18.103 +extern int32 sound4EnvelopeATL; 18.104 +extern int32 sound4EnvelopeUpDown; 18.105 +extern int32 sound4EnvelopeATLReload; 18.106 + 18.107 +extern int32 soundEnableFlag; 18.108 +extern int32 soundMutedFlag; 18.109 + 18.110 +extern int32 soundFreqRatio[8]; 18.111 +extern int32 soundShiftClock[16]; 18.112 + 18.113 +extern s16 soundFilter[4000]; 18.114 +extern s16 soundLeft[5]; 18.115 +extern s16 soundRight[5]; 18.116 +extern int32 soundEchoIndex; 18.117 +extern bool8 soundEcho; 18.118 +extern bool8 soundLowPass; 18.119 +extern bool8 soundReverse; 18.120 +extern bool8 soundOffFlag; 18.121 + 18.122 +bool8 gbDigitalSound = false; 18.123 + 18.124 +void gbSoundEvent(register u16 address, register int data) 18.125 +{ 18.126 + int freq = 0; 18.127 + 18.128 + gbMemory[address] = data; 18.129 + 18.130 +#ifndef FINAL_VERSION 18.131 + if (soundDebug) 18.132 + { 18.133 + // don't translate. debug only 18.134 + log("Sound event: %08lx %02x\n", address, data); 18.135 + } 18.136 +#endif 18.137 + switch (address) 18.138 + { 18.139 + case NR10: 18.140 + sound1SweepATL = sound1SweepATLReload = 344 * ((data >> 4) & 7); 18.141 + sound1SweepSteps = data & 7; 18.142 + sound1SweepUpDown = data & 0x08; 18.143 + sound1SweepStep = 0; 18.144 + break; 18.145 + case NR11: 18.146 + sound1Wave = soundWavePattern[data >> 6]; 18.147 + sound1ATL = 172 * (64 - (data & 0x3f)); 18.148 + break; 18.149 + case NR12: 18.150 + sound1EnvelopeVolume = data >> 4; 18.151 + sound1EnvelopeUpDown = data & 0x08; 18.152 + sound1EnvelopeATLReload = sound1EnvelopeATL = 689 * (data & 7); 18.153 + break; 18.154 + case NR13: 18.155 + freq = (((int)(gbMemory[NR14] & 7)) << 8) | data; 18.156 + sound1ATL = 172 * (64 - (gbMemory[NR11] & 0x3f)); 18.157 + freq = 2048 - freq; 18.158 + if (freq) 18.159 + { 18.160 + sound1Skip = SOUND_MAGIC / freq; 18.161 + } 18.162 + else 18.163 + sound1Skip = 0; 18.164 + break; 18.165 + case NR14: 18.166 + freq = (((int)(data & 7) << 8) | gbMemory[NR13]); 18.167 + freq = 2048 - freq; 18.168 + sound1ATL = 172 * (64 - (gbMemory[NR11] & 0x3f)); 18.169 + sound1Continue = data & 0x40; 18.170 + if (freq) 18.171 + { 18.172 + sound1Skip = SOUND_MAGIC / freq; 18.173 + } 18.174 + else 18.175 + sound1Skip = 0; 18.176 + if (data & 0x80) 18.177 + { 18.178 + gbMemory[NR52] |= 1; 18.179 + sound1EnvelopeVolume = gbMemory[NR12] >> 4; 18.180 + sound1EnvelopeUpDown = gbMemory[NR12] & 0x08; 18.181 + sound1ATL = 172 * (64 - (gbMemory[NR11] & 0x3f)); 18.182 + sound1EnvelopeATLReload = sound1EnvelopeATL = 689 * (gbMemory[NR12] & 7); 18.183 + sound1SweepATL = sound1SweepATLReload = 344 * ((gbMemory[NR10] >> 4) & 7); 18.184 + sound1SweepSteps = gbMemory[NR10] & 7; 18.185 + sound1SweepUpDown = gbMemory[NR10] & 0x08; 18.186 + sound1SweepStep = 0; 18.187 + 18.188 + sound1Index = 0; 18.189 + sound1On = 1; 18.190 + } 18.191 + break; 18.192 + case NR21: 18.193 + sound2Wave = soundWavePattern[data >> 6]; 18.194 + sound2ATL = 172 * (64 - (data & 0x3f)); 18.195 + break; 18.196 + case NR22: 18.197 + sound2EnvelopeVolume = data >> 4; 18.198 + sound2EnvelopeUpDown = data & 0x08; 18.199 + sound2EnvelopeATLReload = sound2EnvelopeATL = 689 * (data & 7); 18.200 + break; 18.201 + case NR23: 18.202 + freq = (((int)(gbMemory[NR24] & 7)) << 8) | data; 18.203 + sound2ATL = 172 * (64 - (gbMemory[NR21] & 0x3f)); 18.204 + freq = 2048 - freq; 18.205 + if (freq) 18.206 + { 18.207 + sound2Skip = SOUND_MAGIC / freq; 18.208 + } 18.209 + else 18.210 + sound2Skip = 0; 18.211 + break; 18.212 + case NR24: 18.213 + freq = (((int)(data & 7) << 8) | gbMemory[NR23]); 18.214 + freq = 2048 - freq; 18.215 + sound2ATL = 172 * (64 - (gbMemory[NR21] & 0x3f)); 18.216 + sound2Continue = data & 0x40; 18.217 + if (freq) 18.218 + { 18.219 + sound2Skip = SOUND_MAGIC / freq; 18.220 + } 18.221 + else 18.222 + sound2Skip = 0; 18.223 + if (data & 0x80) 18.224 + { 18.225 + gbMemory[NR52] |= 2; 18.226 + sound2EnvelopeVolume = gbMemory[NR22] >> 4; 18.227 + sound2EnvelopeUpDown = gbMemory[NR22] & 0x08; 18.228 + sound2ATL = 172 * (64 - (gbMemory[NR21] & 0x3f)); 18.229 + sound2EnvelopeATLReload = sound2EnvelopeATL = 689 * (gbMemory[NR22] & 7); 18.230 + 18.231 + sound2Index = 0; 18.232 + sound2On = 1; 18.233 + } 18.234 + break; 18.235 + case NR30: 18.236 + if (!(data & 0x80)) 18.237 + { 18.238 + gbMemory[NR52] &= 0xfb; 18.239 + sound3On = 0; 18.240 + } 18.241 + break; 18.242 + case NR31: 18.243 + sound3ATL = 172 * (256 - data); 18.244 + break; 18.245 + case NR32: 18.246 + sound3OutputLevel = (data >> 5) & 3; 18.247 + break; 18.248 + case NR33: 18.249 + freq = 2048 - (((int)(gbMemory[NR34] & 7) << 8) | data); 18.250 + if (freq) 18.251 + { 18.252 + sound3Skip = SOUND_MAGIC_2 / freq; 18.253 + } 18.254 + else 18.255 + sound3Skip = 0; 18.256 + break; 18.257 + case NR34: 18.258 + freq = 2048 - (((data & 7) << 8) | (int)gbMemory[NR33]); 18.259 + if (freq) 18.260 + { 18.261 + sound3Skip = SOUND_MAGIC_2 / freq; 18.262 + } 18.263 + else 18.264 + { 18.265 + sound3Skip = 0; 18.266 + } 18.267 + sound3Continue = data & 0x40; 18.268 + if ((data & 0x80) && (gbMemory[NR30] & 0x80)) 18.269 + { 18.270 + gbMemory[NR52] |= 4; 18.271 + sound3ATL = 172 * (256 - gbMemory[NR31]); 18.272 + sound3Index = 0; 18.273 + sound3On = 1; 18.274 + } 18.275 + break; 18.276 + case NR41: 18.277 + sound4ATL = 172 * (64 - (data & 0x3f)); 18.278 + break; 18.279 + case NR42: 18.280 + sound4EnvelopeVolume = data >> 4; 18.281 + sound4EnvelopeUpDown = data & 0x08; 18.282 + sound4EnvelopeATLReload = sound4EnvelopeATL = 689 * (data & 7); 18.283 + break; 18.284 + case NR43: 18.285 + freq = soundFreqRatio[data & 7]; 18.286 + sound4NSteps = data & 0x08; 18.287 + 18.288 + sound4Skip = freq * NOISE_MAGIC; 18.289 + 18.290 + sound4Clock = data >> 4; 18.291 + 18.292 + freq = freq / soundShiftClock[sound4Clock]; 18.293 + 18.294 + sound4ShiftSkip = freq * NOISE_MAGIC; 18.295 + 18.296 + break; 18.297 + case NR44: 18.298 + sound4Continue = data & 0x40; 18.299 + if (data & 0x80) 18.300 + { 18.301 + gbMemory[NR52] |= 8; 18.302 + sound4EnvelopeVolume = gbMemory[NR42] >> 4; 18.303 + sound4EnvelopeUpDown = gbMemory[NR42] & 0x08; 18.304 + sound4ATL = 172 * (64 - (gbMemory[NR41] & 0x3f)); 18.305 + sound4EnvelopeATLReload = sound4EnvelopeATL = 689 * (gbMemory[NR42] & 7); 18.306 + 18.307 + sound4On = 1; 18.308 + 18.309 + sound4Index = 0; 18.310 + sound4ShiftIndex = 0; 18.311 + 18.312 + freq = soundFreqRatio[gbMemory[NR43] & 7]; 18.313 + 18.314 + sound4Skip = freq * NOISE_MAGIC; 18.315 + 18.316 + sound4NSteps = gbMemory[NR43] & 0x08; 18.317 + 18.318 + freq = freq / soundShiftClock[gbMemory[NR43] >> 4]; 18.319 + 18.320 + sound4ShiftSkip = freq * NOISE_MAGIC; 18.321 + if (sound4NSteps) 18.322 + sound4ShiftRight = 0x7f; 18.323 + else 18.324 + sound4ShiftRight = 0x7fff; 18.325 + } 18.326 + break; 18.327 + case NR50: 18.328 + soundVIN = data & 0x88; 18.329 + soundLevel1 = data & 7; 18.330 + soundLevel2 = (data >> 4) & 7; 18.331 + break; 18.332 + case NR51: 18.333 + soundBalance = (data & soundEnableFlag); 18.334 + gbMemory[address] = data; 18.335 + break; 18.336 + case NR52: 18.337 + soundMasterOn = data & 0x80; 18.338 + if (!(data & 0x80)) 18.339 + { 18.340 + sound1On = 0; 18.341 + sound2On = 0; 18.342 + sound3On = 0; 18.343 + sound4On = 0; 18.344 + } 18.345 + break; 18.346 + } 18.347 + 18.348 + gbDigitalSound = true; 18.349 + 18.350 + if (sound1On && sound1EnvelopeVolume != 0) 18.351 + gbDigitalSound = false; 18.352 + if (sound2On && sound2EnvelopeVolume != 0) 18.353 + gbDigitalSound = false; 18.354 + if (sound3On && sound3OutputLevel != 0) 18.355 + gbDigitalSound = false; 18.356 + if (sound4On && sound4EnvelopeVolume != 0) 18.357 + gbDigitalSound = false; 18.358 +} 18.359 + 18.360 +void gbSoundChannel1() 18.361 +{ 18.362 + int vol = sound1EnvelopeVolume; 18.363 + 18.364 + int freq = 0; 18.365 + 18.366 + int value = 0; 18.367 + 18.368 + if (sound1On && (sound1ATL || !sound1Continue)) 18.369 + { 18.370 + sound1Index += soundQuality * sound1Skip; 18.371 + sound1Index &= 0x1fffffff; 18.372 + 18.373 + value = ((s8)sound1Wave[sound1Index >> 24]) * vol; 18.374 + } 18.375 + 18.376 + soundBuffer[0][soundIndex] = value; 18.377 + 18.378 + if (sound1On) 18.379 + { 18.380 + if (sound1ATL) 18.381 + { 18.382 + sound1ATL -= soundQuality; 18.383 + 18.384 + if (sound1ATL <= 0 && sound1Continue) 18.385 + { 18.386 + gbMemory[NR52] &= 0xfe; 18.387 + sound1On = 0; 18.388 + } 18.389 + } 18.390 + 18.391 + if (sound1EnvelopeATL) 18.392 + { 18.393 + sound1EnvelopeATL -= soundQuality; 18.394 + 18.395 + if (sound1EnvelopeATL <= 0) 18.396 + { 18.397 + if (sound1EnvelopeUpDown) 18.398 + { 18.399 + if (sound1EnvelopeVolume < 15) 18.400 + sound1EnvelopeVolume++; 18.401 + } 18.402 + else 18.403 + { 18.404 + if (sound1EnvelopeVolume) 18.405 + sound1EnvelopeVolume--; 18.406 + } 18.407 + 18.408 + sound1EnvelopeATL += sound1EnvelopeATLReload; 18.409 + } 18.410 + } 18.411 + 18.412 + if (sound1SweepATL) 18.413 + { 18.414 + sound1SweepATL -= soundQuality; 18.415 + 18.416 + if (sound1SweepATL <= 0) 18.417 + { 18.418 + freq = (((int)(gbMemory[NR14] & 7) << 8) | gbMemory[NR13]); 18.419 + 18.420 + int updown = 1; 18.421 + 18.422 + if (sound1SweepUpDown) 18.423 + updown = -1; 18.424 + 18.425 + int newfreq = 0; 18.426 + if (sound1SweepSteps) 18.427 + { 18.428 + newfreq = freq + updown * freq / (1 << sound1SweepSteps); 18.429 + if (newfreq == freq) 18.430 + newfreq = 0; 18.431 + } 18.432 + else 18.433 + newfreq = freq; 18.434 + 18.435 + if (newfreq < 0) 18.436 + { 18.437 + sound1SweepATL += sound1SweepATLReload; 18.438 + } 18.439 + else if (newfreq > 2047) 18.440 + { 18.441 + sound1SweepATL = 0; 18.442 + sound1On = 0; 18.443 + gbMemory[NR52] &= 0xfe; 18.444 + } 18.445 + else 18.446 + { 18.447 + sound1SweepATL += sound1SweepATLReload; 18.448 + sound1Skip = SOUND_MAGIC / (2048 - newfreq); 18.449 + 18.450 + gbMemory[NR13] = newfreq & 0xff; 18.451 + gbMemory[NR14] = (gbMemory[NR14] & 0xf8) | ((newfreq >> 8) & 7); 18.452 + } 18.453 + } 18.454 + } 18.455 + } 18.456 +} 18.457 + 18.458 +void gbSoundChannel2() 18.459 +{ 18.460 + // int freq = 0; 18.461 + int vol = sound2EnvelopeVolume; 18.462 + 18.463 + int value = 0; 18.464 + 18.465 + if (sound2On && (sound2ATL || !sound2Continue)) 18.466 + { 18.467 + sound2Index += soundQuality * sound2Skip; 18.468 + sound2Index &= 0x1fffffff; 18.469 + 18.470 + value = ((s8)sound2Wave[sound2Index >> 24]) * vol; 18.471 + } 18.472 + 18.473 + soundBuffer[1][soundIndex] = value; 18.474 + 18.475 + if (sound2On) 18.476 + { 18.477 + if (sound2ATL) 18.478 + { 18.479 + sound2ATL -= soundQuality; 18.480 + 18.481 + if (sound2ATL <= 0 && sound2Continue) 18.482 + { 18.483 + gbMemory[NR52] &= 0xfd; 18.484 + sound2On = 0; 18.485 + } 18.486 + } 18.487 + 18.488 + if (sound2EnvelopeATL) 18.489 + { 18.490 + sound2EnvelopeATL -= soundQuality; 18.491 + 18.492 + if (sound2EnvelopeATL <= 0) 18.493 + { 18.494 + if (sound2EnvelopeUpDown) 18.495 + { 18.496 + if (sound2EnvelopeVolume < 15) 18.497 + sound2EnvelopeVolume++; 18.498 + } 18.499 + else 18.500 + { 18.501 + if (sound2EnvelopeVolume) 18.502 + sound2EnvelopeVolume--; 18.503 + } 18.504 + sound2EnvelopeATL += sound2EnvelopeATLReload; 18.505 + } 18.506 + } 18.507 + } 18.508 +} 18.509 + 18.510 +void gbSoundChannel3() 18.511 +{ 18.512 + int value = sound3Last; 18.513 + 18.514 + if (sound3On && (sound3ATL || !sound3Continue)) 18.515 + { 18.516 + sound3Index += soundQuality * sound3Skip; 18.517 + sound3Index &= 0x1fffffff; 18.518 + 18.519 + value = gbMemory[0xff30 + (sound3Index >> 25)]; 18.520 + 18.521 + if ((sound3Index & 0x01000000)) 18.522 + { 18.523 + value &= 0x0f; 18.524 + } 18.525 + else 18.526 + { 18.527 + value >>= 4; 18.528 + } 18.529 + 18.530 + value -= 8; 18.531 + value *= 2; 18.532 + 18.533 + switch (sound3OutputLevel) 18.534 + { 18.535 + case 0: 18.536 + value = 0; 18.537 + break; 18.538 + case 1: 18.539 + break; 18.540 + case 2: 18.541 + value = (value >> 1); 18.542 + break; 18.543 + case 3: 18.544 + value = (value >> 2); 18.545 + break; 18.546 + } 18.547 + //value += 1; 18.548 + sound3Last = value; 18.549 + } 18.550 + 18.551 + soundBuffer[2][soundIndex] = value; 18.552 + 18.553 + if (sound3On) 18.554 + { 18.555 + if (sound3ATL) 18.556 + { 18.557 + sound3ATL -= soundQuality; 18.558 + 18.559 + if (sound3ATL <= 0 && sound3Continue) 18.560 + { 18.561 + gbMemory[NR52] &= 0xfb; 18.562 + sound3On = 0; 18.563 + } 18.564 + } 18.565 + } 18.566 +} 18.567 + 18.568 +void gbSoundChannel4() 18.569 +{ 18.570 + int vol = sound4EnvelopeVolume; 18.571 + 18.572 + int value = 0; 18.573 + 18.574 + if (sound4Clock <= 0x0c) 18.575 + { 18.576 + if (sound4On && (sound4ATL || !sound4Continue)) 18.577 + { 18.578 + #define NOISE_ONE_SAMP_SCALE 0x200000 18.579 + 18.580 + sound4Index += soundQuality * sound4Skip; 18.581 + sound4ShiftIndex += soundQuality * sound4ShiftSkip; 18.582 + 18.583 + if (sound4NSteps) 18.584 + { 18.585 + while (sound4ShiftIndex >= NOISE_ONE_SAMP_SCALE) 18.586 + { 18.587 + sound4ShiftRight = (((sound4ShiftRight << 6) ^ 18.588 + (sound4ShiftRight << 5)) & 0x40) | 18.589 + (sound4ShiftRight >> 1); 18.590 + sound4ShiftIndex -= NOISE_ONE_SAMP_SCALE; 18.591 + } 18.592 + } 18.593 + else 18.594 + { 18.595 + while (sound4ShiftIndex >= NOISE_ONE_SAMP_SCALE) 18.596 + { 18.597 + sound4ShiftRight = (((sound4ShiftRight << 14) ^ 18.598 + (sound4ShiftRight << 13)) & 0x4000) | 18.599 + (sound4ShiftRight >> 1); 18.600 + 18.601 + sound4ShiftIndex -= NOISE_ONE_SAMP_SCALE; 18.602 + } 18.603 + } 18.604 + 18.605 + sound4Index %= NOISE_ONE_SAMP_SCALE; 18.606 + sound4ShiftIndex %= NOISE_ONE_SAMP_SCALE; 18.607 + 18.608 + value = ((sound4ShiftRight & 1) * 2 - 1) * vol; 18.609 + } 18.610 + else 18.611 + { 18.612 + value = 0; 18.613 + } 18.614 + } 18.615 + 18.616 + soundBuffer[3][soundIndex] = value; 18.617 + 18.618 + if (sound4On) 18.619 + { 18.620 + if (sound4ATL) 18.621 + { 18.622 + sound4ATL -= soundQuality; 18.623 + 18.624 + if (sound4ATL <= 0 && sound4Continue) 18.625 + { 18.626 + gbMemory[NR52] &= 0xfd; 18.627 + sound4On = 0; 18.628 + } 18.629 + } 18.630 + 18.631 + if (sound4EnvelopeATL) 18.632 + { 18.633 + sound4EnvelopeATL -= soundQuality; 18.634 + 18.635 + if (sound4EnvelopeATL <= 0) 18.636 + { 18.637 + if (sound4EnvelopeUpDown) 18.638 + { 18.639 + if (sound4EnvelopeVolume < 15) 18.640 + sound4EnvelopeVolume++; 18.641 + } 18.642 + else 18.643 + { 18.644 + if (sound4EnvelopeVolume) 18.645 + sound4EnvelopeVolume--; 18.646 + } 18.647 + sound4EnvelopeATL += sound4EnvelopeATLReload; 18.648 + } 18.649 + } 18.650 + } 18.651 +} 18.652 + 18.653 +void gbSoundMix() 18.654 +{ 18.655 + int res = 0; 18.656 + 18.657 + if (gbMemory) 18.658 + soundBalance = (gbMemory[NR51] & soundEnableFlag & ~soundMutedFlag); 18.659 + 18.660 + if (soundBalance & 16) 18.661 + { 18.662 + res += ((s8)soundBuffer[0][soundIndex]); 18.663 + } 18.664 + if (soundBalance & 32) 18.665 + { 18.666 + res += ((s8)soundBuffer[1][soundIndex]); 18.667 + } 18.668 + if (soundBalance & 64) 18.669 + { 18.670 + res += ((s8)soundBuffer[2][soundIndex]); 18.671 + } 18.672 + if (soundBalance & 128) 18.673 + { 18.674 + res += ((s8)soundBuffer[3][soundIndex]); 18.675 + } 18.676 + 18.677 + if (gbDigitalSound) 18.678 + res = soundLevel1 * 256; 18.679 + else 18.680 + res *= soundLevel1 * 60; 18.681 + 18.682 + if (soundEcho) 18.683 + { 18.684 + res *= 2; 18.685 + res += soundFilter[soundEchoIndex]; 18.686 + res /= 2; 18.687 + soundFilter[soundEchoIndex++] = res; 18.688 + } 18.689 + 18.690 + if (soundLowPass) 18.691 + { 18.692 + soundLeft[4] = soundLeft[3]; 18.693 + soundLeft[3] = soundLeft[2]; 18.694 + soundLeft[2] = soundLeft[1]; 18.695 + soundLeft[1] = soundLeft[0]; 18.696 + soundLeft[0] = res; 18.697 + res = (soundLeft[4] + 2 * soundLeft[3] + 8 * soundLeft[2] + 2 * soundLeft[1] + 18.698 + soundLeft[0]) / 14; 18.699 + } 18.700 + 18.701 + bool noSpecialEffects = false; 18.702 +#if (defined(WIN32) && !defined(SDL)) 18.703 + if (theApp.soundRecording || theApp.aviRecording || theApp.nvAudioLog) 18.704 + noSpecialEffects = true; 18.705 +#endif 18.706 + 18.707 + if (!noSpecialEffects) 18.708 + { 18.709 + switch (soundVolume) 18.710 + { 18.711 + case 0: 18.712 + case 1: 18.713 + case 2: 18.714 + case 3: 18.715 + res *= (soundVolume + 1); 18.716 + break; 18.717 + case 4: 18.718 + res >>= 2; 18.719 + break; 18.720 + case 5: 18.721 + res >>= 1; 18.722 + break; 18.723 + } 18.724 + } 18.725 + 18.726 + if (res > 32767) 18.727 + res = 32767; 18.728 + if (res < -32768) 18.729 + res = -32768; 18.730 + 18.731 + if (soundReverse && !noSpecialEffects) 18.732 + { 18.733 + soundFinalWave[++soundBufferIndex] = res; 18.734 + if ((soundFrameSoundWritten + 1) >= countof(soundFrameSound)) 18.735 + /*assert(false)*/; 18.736 + else 18.737 + soundFrameSound[++soundFrameSoundWritten] = res; 18.738 + } 18.739 + else 18.740 + { 18.741 + soundFinalWave[soundBufferIndex++] = res; 18.742 + if (soundFrameSoundWritten >= countof(soundFrameSound)) 18.743 + /*assert(false)*/; 18.744 + else 18.745 + soundFrameSound[soundFrameSoundWritten++] = res; 18.746 + } 18.747 + 18.748 + res = 0; 18.749 + 18.750 + if (soundBalance & 1) 18.751 + { 18.752 + res += ((s8)soundBuffer[0][soundIndex]); 18.753 + } 18.754 + if (soundBalance & 2) 18.755 + { 18.756 + res += ((s8)soundBuffer[1][soundIndex]); 18.757 + } 18.758 + if (soundBalance & 4) 18.759 + { 18.760 + res += ((s8)soundBuffer[2][soundIndex]); 18.761 + } 18.762 + if (soundBalance & 8) 18.763 + { 18.764 + res += ((s8)soundBuffer[3][soundIndex]); 18.765 + } 18.766 + 18.767 + if (gbDigitalSound) 18.768 + res = soundLevel2 * 256; 18.769 + else 18.770 + res *= soundLevel2 * 60; 18.771 + 18.772 + if (soundEcho) 18.773 + { 18.774 + res *= 2; 18.775 + res += soundFilter[soundEchoIndex]; 18.776 + res /= 2; 18.777 + soundFilter[soundEchoIndex++] = res; 18.778 + 18.779 + if (soundEchoIndex >= 4000) 18.780 + soundEchoIndex = 0; 18.781 + } 18.782 + 18.783 + if (soundLowPass) 18.784 + { 18.785 + soundRight[4] = soundRight[3]; 18.786 + soundRight[3] = soundRight[2]; 18.787 + soundRight[2] = soundRight[1]; 18.788 + soundRight[1] = soundRight[0]; 18.789 + soundRight[0] = res; 18.790 + res = (soundRight[4] + 2 * soundRight[3] + 8 * soundRight[2] + 2 * soundRight[1] + 18.791 + soundRight[0]) / 14; 18.792 + } 18.793 + 18.794 + if (!noSpecialEffects) 18.795 + { 18.796 + switch (soundVolume) 18.797 + { 18.798 + case 0: 18.799 + case 1: 18.800 + case 2: 18.801 + case 3: 18.802 + res *= (soundVolume + 1); 18.803 + break; 18.804 + case 4: 18.805 + res >>= 2; 18.806 + break; 18.807 + case 5: 18.808 + res >>= 1; 18.809 + break; 18.810 + } 18.811 + } 18.812 + 18.813 + if (res > 32767) 18.814 + res = 32767; 18.815 + if (res < -32768) 18.816 + res = -32768; 18.817 + 18.818 + if (soundReverse && !noSpecialEffects) 18.819 + { 18.820 + soundFinalWave[-1 + soundBufferIndex++] = res; 18.821 + if ((soundFrameSoundWritten) >= countof(soundFrameSound)) 18.822 + /*assert(false)*/; 18.823 + else 18.824 + soundFrameSound[-1 + soundFrameSoundWritten++] = res; 18.825 + } 18.826 + else 18.827 + { 18.828 + soundFinalWave[soundBufferIndex++] = res; 18.829 + if ((soundFrameSoundWritten + 1) >= countof(soundFrameSound)) 18.830 + /*assert(false)*/; 18.831 + else 18.832 + soundFrameSound[soundFrameSoundWritten++] = res; 18.833 + } 18.834 +} 18.835 + 18.836 +void gbSoundTick() 18.837 +{ 18.838 + if (systemSoundOn) 18.839 + { 18.840 + if (soundMasterOn) 18.841 + { 18.842 + gbSoundChannel1(); 18.843 + gbSoundChannel2(); 18.844 + gbSoundChannel3(); 18.845 + gbSoundChannel4(); 18.846 + 18.847 + gbSoundMix(); 18.848 + } 18.849 + else 18.850 + { 18.851 + soundFinalWave[soundBufferIndex++] = 0; 18.852 + soundFinalWave[soundBufferIndex++] = 0; 18.853 + if ((soundFrameSoundWritten + 1) >= countof(soundFrameSound)) 18.854 + /*assert(false)*/; 18.855 + else 18.856 + { 18.857 + soundFrameSound[soundFrameSoundWritten++] = 0; 18.858 + soundFrameSound[soundFrameSoundWritten++] = 0; 18.859 + } 18.860 + } 18.861 + 18.862 + soundIndex++; 18.863 + 18.864 + if (2 * soundBufferIndex >= soundBufferLen) 18.865 + { 18.866 + if (systemSoundOn) 18.867 + { 18.868 + if (soundPaused) 18.869 + { 18.870 + extern void soundResume(); 18.871 + soundResume(); 18.872 + } 18.873 + 18.874 + systemSoundWriteToBuffer(); 18.875 + } 18.876 + soundIndex = 0; 18.877 + soundBufferIndex = 0; 18.878 + } 18.879 + } 18.880 +} 18.881 + 18.882 +void gbSoundReset() 18.883 +{ 18.884 + soundPaused = 1; 18.885 + soundPlay = 0; 18.886 + SOUND_CLOCK_TICKS = soundQuality * GB_USE_TICKS_AS; 18.887 +// soundTicks = SOUND_CLOCK_TICKS; 18.888 + soundTicks = 0; 18.889 + soundNextPosition = 0; 18.890 + soundMasterOn = 1; 18.891 + soundIndex = 0; 18.892 + soundBufferIndex = 0; 18.893 + soundLevel1 = 7; 18.894 + soundLevel2 = 7; 18.895 + soundVIN = 0; 18.896 + 18.897 + sound1On = 0; 18.898 + sound1ATL = 0; 18.899 + sound1Skip = 0; 18.900 + sound1Index = 0; 18.901 + sound1Continue = 0; 18.902 + sound1EnvelopeVolume = 0; 18.903 + sound1EnvelopeATL = 0; 18.904 + sound1EnvelopeUpDown = 0; 18.905 + sound1EnvelopeATLReload = 0; 18.906 + sound1SweepATL = 0; 18.907 + sound1SweepATLReload = 0; 18.908 + sound1SweepSteps = 0; 18.909 + sound1SweepUpDown = 0; 18.910 + sound1SweepStep = 0; 18.911 + sound1Wave = soundWavePattern[2]; 18.912 + 18.913 + sound2On = 0; 18.914 + sound2ATL = 0; 18.915 + sound2Skip = 0; 18.916 + sound2Index = 0; 18.917 + sound2Continue = 0; 18.918 + sound2EnvelopeVolume = 0; 18.919 + sound2EnvelopeATL = 0; 18.920 + sound2EnvelopeUpDown = 0; 18.921 + sound2EnvelopeATLReload = 0; 18.922 + sound2Wave = soundWavePattern[2]; 18.923 + 18.924 + sound3On = 0; 18.925 + sound3ATL = 0; 18.926 + sound3Skip = 0; 18.927 + sound3Index = 0; 18.928 + sound3Continue = 0; 18.929 + sound3OutputLevel = 0; 18.930 + 18.931 + sound4On = 0; 18.932 + sound4Clock = 0; 18.933 + sound4ATL = 0; 18.934 + sound4Skip = 0; 18.935 + sound4Index = 0; 18.936 + sound4ShiftRight = 0x7f; 18.937 + sound4NSteps = 0; 18.938 + sound4CountDown = 0; 18.939 + sound4Continue = 0; 18.940 + sound4EnvelopeVolume = 0; 18.941 + sound4EnvelopeATL = 0; 18.942 + sound4EnvelopeUpDown = 0; 18.943 + sound4EnvelopeATLReload = 0; 18.944 + 18.945 + // don't translate 18.946 + if (soundDebug) 18.947 + { 18.948 + log("*** Sound Init ***\n"); 18.949 + } 18.950 + 18.951 + gbSoundEvent(0xff10, 0x80); 18.952 + gbSoundEvent(0xff11, 0xbf); 18.953 + gbSoundEvent(0xff12, 0xf3); 18.954 + gbSoundEvent(0xff14, 0xbf); 18.955 + gbSoundEvent(0xff16, 0x3f); 18.956 + gbSoundEvent(0xff17, 0x00); 18.957 + gbSoundEvent(0xff19, 0xbf); 18.958 + 18.959 + gbSoundEvent(0xff1a, 0x7f); 18.960 + gbSoundEvent(0xff1b, 0xff); 18.961 + gbSoundEvent(0xff1c, 0xbf); 18.962 + gbSoundEvent(0xff1e, 0xbf); 18.963 + 18.964 + gbSoundEvent(0xff20, 0xff); 18.965 + gbSoundEvent(0xff21, 0x00); 18.966 + gbSoundEvent(0xff22, 0x00); 18.967 + gbSoundEvent(0xff23, 0xbf); 18.968 + gbSoundEvent(0xff24, 0x77); 18.969 + gbSoundEvent(0xff25, 0xf3); 18.970 + 18.971 + gbSoundEvent(0xff26, 0xf0); 18.972 + 18.973 + // don't translate 18.974 + if (soundDebug) 18.975 + { 18.976 + log("*** Sound Init Complete ***\n"); 18.977 + } 18.978 + 18.979 + sound1On = 0; 18.980 + sound2On = 0; 18.981 + sound3On = 0; 18.982 + sound4On = 0; 18.983 + 18.984 + int addr = 0xff30; 18.985 + 18.986 + while (addr < 0xff40) 18.987 + { 18.988 + gbMemory[addr++] = 0x00; 18.989 + gbMemory[addr++] = 0xff; 18.990 + } 18.991 + 18.992 + memset(soundFinalWave, 0x00, soundBufferLen); 18.993 + 18.994 + memset(soundFilter, 0, sizeof(soundFilter)); 18.995 + soundEchoIndex = 0; 18.996 +} 18.997 + 18.998 +extern bool soundInit(); 18.999 +extern void soundShutdown(); 18.1000 + 18.1001 +void gbSoundSetQuality(int quality) 18.1002 +{ 18.1003 + if (soundQuality != quality && systemSoundCanChangeQuality()) 18.1004 + { 18.1005 + if (!soundOffFlag) 18.1006 + soundShutdown(); 18.1007 + soundQuality = quality; 18.1008 + soundNextPosition = 0; 18.1009 + if (!soundOffFlag) 18.1010 + soundInit(); 18.1011 + SOUND_CLOCK_TICKS = (gbSpeed ? 2 : 1) * GB_USE_TICKS_AS * soundQuality; 18.1012 + soundIndex = 0; 18.1013 + soundBufferIndex = 0; 18.1014 + } 18.1015 + else 18.1016 + { 18.1017 + soundNextPosition = 0; 18.1018 + SOUND_CLOCK_TICKS = (gbSpeed ? 2 : 1) * GB_USE_TICKS_AS * soundQuality; 18.1019 + soundIndex = 0; 18.1020 + soundBufferIndex = 0; 18.1021 + } 18.1022 +} 18.1023 + 18.1024 +static int32 soundTicks_int32; 18.1025 +static int32 SOUND_CLOCK_TICKS_int32; 18.1026 +variable_desc gbSoundSaveStruct[] = { 18.1027 + { &soundPaused, sizeof(int32) }, 18.1028 + { &soundPlay, sizeof(int32) }, 18.1029 + { &soundTicks_int32, sizeof(int32) }, 18.1030 + { &SOUND_CLOCK_TICKS_int32, sizeof(int32) }, 18.1031 + { &soundLevel1, sizeof(int32) }, 18.1032 + { &soundLevel2, sizeof(int32) }, 18.1033 + { &soundBalance, sizeof(int32) }, 18.1034 + { &soundMasterOn, sizeof(int32) }, 18.1035 + { &soundIndex, sizeof(int32) }, 18.1036 + { &soundVIN, sizeof(int32) }, 18.1037 + { &sound1On, sizeof(int32) }, 18.1038 + { &sound1ATL, sizeof(int32) }, 18.1039 + { &sound1Skip, sizeof(int32) }, 18.1040 + { &sound1Index, sizeof(int32) }, 18.1041 + { &sound1Continue, sizeof(int32) }, 18.1042 + { &sound1EnvelopeVolume, sizeof(int32) }, 18.1043 + { &sound1EnvelopeATL, sizeof(int32) }, 18.1044 + { &sound1EnvelopeATLReload, sizeof(int32) }, 18.1045 + { &sound1EnvelopeUpDown, sizeof(int32) }, 18.1046 + { &sound1SweepATL, sizeof(int32) }, 18.1047 + { &sound1SweepATLReload, sizeof(int32) }, 18.1048 + { &sound1SweepSteps, sizeof(int32) }, 18.1049 + { &sound1SweepUpDown, sizeof(int32) }, 18.1050 + { &sound1SweepStep, sizeof(int32) }, 18.1051 + { &sound2On, sizeof(int32) }, 18.1052 + { &sound2ATL, sizeof(int32) }, 18.1053 + { &sound2Skip, sizeof(int32) }, 18.1054 + { &sound2Index, sizeof(int32) }, 18.1055 + { &sound2Continue, sizeof(int32) }, 18.1056 + { &sound2EnvelopeVolume, sizeof(int32) }, 18.1057 + { &sound2EnvelopeATL, sizeof(int32) }, 18.1058 + { &sound2EnvelopeATLReload, sizeof(int32) }, 18.1059 + { &sound2EnvelopeUpDown, sizeof(int32) }, 18.1060 + { &sound3On, sizeof(int32) }, 18.1061 + { &sound3ATL, sizeof(int32) }, 18.1062 + { &sound3Skip, sizeof(int32) }, 18.1063 + { &sound3Index, sizeof(int32) }, 18.1064 + { &sound3Continue, sizeof(int32) }, 18.1065 + { &sound3OutputLevel, sizeof(int32) }, 18.1066 + { &sound4On, sizeof(int32) }, 18.1067 + { &sound4ATL, sizeof(int32) }, 18.1068 + { &sound4Skip, sizeof(int32) }, 18.1069 + { &sound4Index, sizeof(int32) }, 18.1070 + { &sound4Clock, sizeof(int32) }, 18.1071 + { &sound4ShiftRight, sizeof(int32) }, 18.1072 + { &sound4ShiftSkip, sizeof(int32) }, 18.1073 + { &sound4ShiftIndex, sizeof(int32) }, 18.1074 + { &sound4NSteps, sizeof(int32) }, 18.1075 + { &sound4CountDown, sizeof(int32) }, 18.1076 + { &sound4Continue, sizeof(int32) }, 18.1077 + { &sound4EnvelopeVolume, sizeof(int32) }, 18.1078 + { &sound4EnvelopeATL, sizeof(int32) }, 18.1079 + { &sound4EnvelopeATLReload, sizeof(int32) }, 18.1080 + { &sound4EnvelopeUpDown, sizeof(int32) }, 18.1081 + { &soundEnableFlag, sizeof(int32) }, 18.1082 + { NULL, 0 } 18.1083 +}; 18.1084 + 18.1085 +//variable_desc gbSoundSaveStructV2[] = { 18.1086 +// { &soundTicks, sizeof(soundtick_t) }, 18.1087 +// { &SOUND_CLOCK_TICKS, sizeof(soundtick_t) }, 18.1088 +// { &GB_USE_TICKS_AS, sizeof(soundtick_t) }, 18.1089 +// { NULL, 0 } 18.1090 +//}; 18.1091 + 18.1092 +void gbSoundSaveGame(gzFile gzFile) 18.1093 +{ 18.1094 + soundTicks_int32 = (int32) soundTicks; 18.1095 + SOUND_CLOCK_TICKS_int32 = (int32) SOUND_CLOCK_TICKS; 18.1096 + 18.1097 + utilWriteData(gzFile, gbSoundSaveStruct); 18.1098 + 18.1099 + utilGzWrite(gzFile, soundBuffer, 4 * 735); 18.1100 + utilGzWrite(gzFile, soundFinalWave, 2 * 735); 18.1101 + utilGzWrite(gzFile, &soundQuality, sizeof(int32)); 18.1102 + 18.1103 + //utilWriteData(gzFile, gbSoundSaveStructV2); 18.1104 +} 18.1105 + 18.1106 +void gbSoundReadGame(int version, gzFile gzFile) 18.1107 +{ 18.1108 + int32 oldSoundPaused = soundPaused; 18.1109 + int32 oldSoundEnableFlag = soundEnableFlag; 18.1110 + utilReadData(gzFile, gbSoundSaveStruct); 18.1111 + soundPaused = oldSoundPaused; 18.1112 + soundEnableFlag = oldSoundEnableFlag; 18.1113 + 18.1114 + soundBufferIndex = soundIndex * 2; 18.1115 + 18.1116 + utilGzRead(gzFile, soundBuffer, 4 * 735); 18.1117 + utilGzRead(gzFile, soundFinalWave, 2 * 735); 18.1118 + 18.1119 + if (version >= 7) 18.1120 + { 18.1121 + int quality = 1; 18.1122 + utilGzRead(gzFile, &quality, sizeof(int32)); 18.1123 + gbSoundSetQuality(quality); 18.1124 + } 18.1125 + else 18.1126 + { 18.1127 + soundQuality = -1; 18.1128 + gbSoundSetQuality(1); 18.1129 + } 18.1130 + 18.1131 + sound1Wave = soundWavePattern[gbMemory[NR11] >> 6]; 18.1132 + sound2Wave = soundWavePattern[gbMemory[NR21] >> 6]; 18.1133 + 18.1134 + //if(version >= 14) { 18.1135 + // utilReadData(gzFile, gbSoundSaveStructV2); 18.1136 + //} 18.1137 + //else { 18.1138 + soundTicks = (soundtick_t) soundTicks_int32; 18.1139 + SOUND_CLOCK_TICKS = (soundtick_t) SOUND_CLOCK_TICKS_int32; 18.1140 + //} 18.1141 +} 18.1142 +
19.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 19.2 +++ b/src/gb/gbSound.h Sat Mar 03 11:44:47 2012 -0600 19.3 @@ -0,0 +1,51 @@ 19.4 +#ifndef VBA_GB_SOUND_H 19.5 +#define VBA_GB_SOUND_H 19.6 + 19.7 +#if _MSC_VER > 1000 19.8 +#pragma once 19.9 +#endif // _MSC_VER > 1000 19.10 + 19.11 +#define NR10 0xff10 19.12 +#define NR11 0xff11 19.13 +#define NR12 0xff12 19.14 +#define NR13 0xff13 19.15 +#define NR14 0xff14 19.16 +#define NR21 0xff16 19.17 +#define NR22 0xff17 19.18 +#define NR23 0xff18 19.19 +#define NR24 0xff19 19.20 +#define NR30 0xff1a 19.21 +#define NR31 0xff1b 19.22 +#define NR32 0xff1c 19.23 +#define NR33 0xff1d 19.24 +#define NR34 0xff1e 19.25 +#define NR41 0xff20 19.26 +#define NR42 0xff21 19.27 +#define NR43 0xff22 19.28 +#define NR44 0xff23 19.29 +#define NR50 0xff24 19.30 +#define NR51 0xff25 19.31 +#define NR52 0xff26 19.32 + 19.33 +#define SOUND_EVENT(address, value) \ 19.34 + gbSoundEvent(address, value) 19.35 + 19.36 +extern void gbSoundTick(); 19.37 +extern void gbSoundPause(); 19.38 +extern void gbSoundResume(); 19.39 +extern void gbSoundEnable(int); 19.40 +extern void gbSoundDisable(int); 19.41 +extern int gbSoundGetEnable(); 19.42 +extern void gbSoundReset(); 19.43 +extern void gbSoundSaveGame(gzFile); 19.44 +extern void gbSoundReadGame(int, gzFile); 19.45 +extern void gbSoundEvent(register u16, register int); 19.46 +extern void gbSoundSetQuality(int); 19.47 + 19.48 +typedef int32 soundtick_t; 19.49 + 19.50 +extern soundtick_t soundTicks; 19.51 +extern int32 soundQuality; 19.52 +extern soundtick_t SOUND_CLOCK_TICKS; 19.53 + 19.54 +#endif // VBA_GB_SOUND_H