Mercurial > vba-clojure
diff src/gb/gbMemory.cpp @ 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 | f9f4f1b99eed |
children |
line wrap: on
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/gb/gbMemory.cpp Sat Mar 03 11:44:47 2012 -0600 1.3 @@ -0,0 +1,1070 @@ 1.4 +#include "gbGlobals.h" 1.5 +#include "gbMemory.h" 1.6 +#include "../common/System.h" 1.7 +#include "../common/movie.h" 1.8 + 1.9 +mapperMBC1 gbDataMBC1 = { 1.10 + 0, // RAM enable 1.11 + 1, // ROM bank 1.12 + 0, // RAM bank 1.13 + 0, // memory model 1.14 + 0, // ROM high address 1.15 + 0 // RAM address 1.16 +}; 1.17 + 1.18 +// MBC1 ROM write registers 1.19 +void mapperMBC1ROM(u16 address, u8 value) 1.20 +{ 1.21 + int tmpAddress = 0; 1.22 + 1.23 + switch (address & 0x6000) 1.24 + { 1.25 + case 0x0000: // RAM enable register 1.26 + gbDataMBC1.mapperRAMEnable = ((value & 0x0a) == 0x0a ? 1 : 0); 1.27 + break; 1.28 + case 0x2000: // ROM bank select 1.29 + // value = value & 0x1f; 1.30 + if (value == 0) 1.31 + value = 1; 1.32 + if (value == gbDataMBC1.mapperROMBank) 1.33 + break; 1.34 + 1.35 + tmpAddress = value << 14; 1.36 + 1.37 + // check current model 1.38 + if (gbDataMBC1.mapperMemoryModel == 0) 1.39 + { 1.40 + // model is 16/8, so we have a high address in use 1.41 + tmpAddress |= (gbDataMBC1.mapperROMHighAddress) << 19; 1.42 + } 1.43 + 1.44 + tmpAddress &= gbRomSizeMask; 1.45 + gbDataMBC1.mapperROMBank = value; 1.46 + gbMemoryMap[0x04] = &gbRom[tmpAddress]; 1.47 + gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; 1.48 + gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; 1.49 + gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; 1.50 + break; 1.51 + case 0x4000: // RAM bank select 1.52 + if (gbDataMBC1.mapperMemoryModel == 1) 1.53 + { 1.54 + // 4/32 model, RAM bank switching provided 1.55 + value = value & 0x03; 1.56 + if (value == gbDataMBC1.mapperRAMBank) 1.57 + break; 1.58 + tmpAddress = value << 13; 1.59 + tmpAddress &= gbRamSizeMask; 1.60 + gbMemoryMap[0x0a] = &gbRam[tmpAddress]; 1.61 + gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000]; 1.62 + gbDataMBC1.mapperRAMBank = value; 1.63 + gbDataMBC1.mapperRAMAddress = tmpAddress; 1.64 + } 1.65 + else 1.66 + { 1.67 + // 16/8, set the high address 1.68 + gbDataMBC1.mapperROMHighAddress = value & 0x03; 1.69 + tmpAddress = gbDataMBC1.mapperROMBank << 14; 1.70 + tmpAddress |= (gbDataMBC1.mapperROMHighAddress) << 19; 1.71 + tmpAddress &= gbRomSizeMask; 1.72 + gbMemoryMap[0x04] = &gbRom[tmpAddress]; 1.73 + gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; 1.74 + gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; 1.75 + gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; 1.76 + } 1.77 + break; 1.78 + case 0x6000: // memory model select 1.79 + gbDataMBC1.mapperMemoryModel = value & 1; 1.80 + break; 1.81 + } 1.82 +} 1.83 + 1.84 +// MBC1 RAM write 1.85 +void mapperMBC1RAM(u16 address, u8 value) 1.86 +{ 1.87 + if (gbDataMBC1.mapperRAMEnable) 1.88 + { 1.89 + if (gbRamSize) 1.90 + { 1.91 + gbWriteMemoryQuick(address, value); 1.92 + systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED; 1.93 + } 1.94 + } 1.95 +} 1.96 + 1.97 +void memoryUpdateMapMBC1() 1.98 +{ 1.99 + int tmpAddress = gbDataMBC1.mapperROMBank << 14; 1.100 + 1.101 + // check current model 1.102 + if (gbDataMBC1.mapperMemoryModel == 1) 1.103 + { 1.104 + // model is 16/8, so we have a high address in use 1.105 + tmpAddress |= (gbDataMBC1.mapperROMHighAddress) << 19; 1.106 + } 1.107 + 1.108 + tmpAddress &= gbRomSizeMask; 1.109 + gbMemoryMap[0x04] = &gbRom[tmpAddress]; 1.110 + gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; 1.111 + gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; 1.112 + gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; 1.113 + 1.114 + if (gbRamSize) 1.115 + { 1.116 + gbMemoryMap[0x0a] = &gbRam[gbDataMBC1.mapperRAMAddress]; 1.117 + gbMemoryMap[0x0b] = &gbRam[gbDataMBC1.mapperRAMAddress + 0x1000]; 1.118 + } 1.119 +} 1.120 + 1.121 +mapperMBC2 gbDataMBC2 = { 1.122 + 0, // RAM enable 1.123 + 1 // ROM bank 1.124 +}; 1.125 + 1.126 +// MBC2 ROM write registers 1.127 +void mapperMBC2ROM(u16 address, u8 value) 1.128 +{ 1.129 + switch (address & 0x6000) 1.130 + { 1.131 + case 0x0000: // RAM enable 1.132 + if (!(address & 0x0100)) 1.133 + { 1.134 + gbDataMBC2.mapperRAMEnable = (value & 0x0f) == 0x0a; 1.135 + } 1.136 + break; 1.137 + case 0x2000: // ROM bank select 1.138 + if (address & 0x0100) 1.139 + { 1.140 + value &= 0x0f; 1.141 + 1.142 + if (value == 0) 1.143 + value = 1; 1.144 + if (gbDataMBC2.mapperROMBank != value) 1.145 + { 1.146 + gbDataMBC2.mapperROMBank = value; 1.147 + 1.148 + int tmpAddress = value << 14; 1.149 + 1.150 + tmpAddress &= gbRomSizeMask; 1.151 + 1.152 + gbMemoryMap[0x04] = &gbRom[tmpAddress]; 1.153 + gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; 1.154 + gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; 1.155 + gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; 1.156 + } 1.157 + } 1.158 + break; 1.159 + } 1.160 +} 1.161 + 1.162 +// MBC2 RAM write 1.163 +void mapperMBC2RAM(u16 address, u8 value) 1.164 +{ 1.165 + if (gbDataMBC2.mapperRAMEnable) 1.166 + { 1.167 + if (gbRamSize && address < 0xa200) 1.168 + { 1.169 + gbWriteMemoryQuick(address, value); 1.170 + systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED; 1.171 + } 1.172 + } 1.173 +} 1.174 + 1.175 +void memoryUpdateMapMBC2() 1.176 +{ 1.177 + int tmpAddress = gbDataMBC2.mapperROMBank << 14; 1.178 + 1.179 + tmpAddress &= gbRomSizeMask; 1.180 + 1.181 + gbMemoryMap[0x04] = &gbRom[tmpAddress]; 1.182 + gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; 1.183 + gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; 1.184 + gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; 1.185 +} 1.186 + 1.187 +mapperMBC3 gbDataMBC3 = { 1.188 + 0, // RAM enable 1.189 + 1, // ROM bank 1.190 + 0, // RAM bank 1.191 + 0, // RAM address 1.192 + 0, // timer clock latch 1.193 + 0, // timer clock register 1.194 + 0, // timer seconds 1.195 + 0, // timer minutes 1.196 + 0, // timer hours 1.197 + 0, // timer days 1.198 + 0, // timer control 1.199 + 0, // timer latched seconds 1.200 + 0, // timer latched minutes 1.201 + 0, // timer latched hours 1.202 + 0, // timer latched days 1.203 + 0, // timer latched control 1.204 + (time_t)-1 // last time 1.205 +}; 1.206 + 1.207 +void memoryUpdateMBC3Clock() 1.208 +{ 1.209 + time_t now; 1.210 + 1.211 + if (VBAMovieActive() || VBAMovieLoading()) 1.212 + now = (time_t)(VBAMovieGetId() + VBAMovieGetFrameCounter()/60); /// FIXME: is /60 the right factor? 1.213 + else 1.214 + now = time(NULL); 1.215 + 1.216 + time_t diff = now - gbDataMBC3.mapperLastTime; 1.217 + if (diff > 0) 1.218 + { 1.219 + // update the clock according to the last update time 1.220 + gbDataMBC3.mapperSeconds += (int)(diff % 60); 1.221 + if (gbDataMBC3.mapperSeconds > 59) 1.222 + { 1.223 + gbDataMBC3.mapperSeconds -= 60; 1.224 + gbDataMBC3.mapperMinutes++; 1.225 + } 1.226 + 1.227 + diff /= 60; 1.228 + 1.229 + gbDataMBC3.mapperMinutes += (int)(diff % 60); 1.230 + if (gbDataMBC3.mapperMinutes > 60) 1.231 + { 1.232 + gbDataMBC3.mapperMinutes -= 60; 1.233 + gbDataMBC3.mapperHours++; 1.234 + } 1.235 + 1.236 + diff /= 60; 1.237 + 1.238 + gbDataMBC3.mapperHours += (int)(diff % 24); 1.239 + if (gbDataMBC3.mapperHours > 24) 1.240 + { 1.241 + gbDataMBC3.mapperHours -= 24; 1.242 + gbDataMBC3.mapperDays++; 1.243 + } 1.244 + diff /= 24; 1.245 + 1.246 + gbDataMBC3.mapperDays += (int)diff; 1.247 + if (gbDataMBC3.mapperDays > 255) 1.248 + { 1.249 + if (gbDataMBC3.mapperDays > 511) 1.250 + { 1.251 + gbDataMBC3.mapperDays %= 512; 1.252 + gbDataMBC3.mapperControl |= 0x80; 1.253 + } 1.254 + gbDataMBC3.mapperControl = (gbDataMBC3.mapperControl & 0xfe) | 1.255 + (gbDataMBC3.mapperDays > 255 ? 1 : 0); 1.256 + } 1.257 + } 1.258 + gbDataMBC3.mapperLastTime = now; 1.259 +} 1.260 + 1.261 +// MBC3 ROM write registers 1.262 +void mapperMBC3ROM(u16 address, u8 value) 1.263 +{ 1.264 + int tmpAddress = 0; 1.265 + 1.266 + switch (address & 0x6000) 1.267 + { 1.268 + case 0x0000: // RAM enable register 1.269 + gbDataMBC3.mapperRAMEnable = ((value & 0x0a) == 0x0a ? 1 : 0); 1.270 + break; 1.271 + case 0x2000: // ROM bank select 1.272 + value = value & 0x7f; 1.273 + if (value == 0) 1.274 + value = 1; 1.275 + if (value == gbDataMBC3.mapperROMBank) 1.276 + break; 1.277 + 1.278 + tmpAddress = value << 14; 1.279 + 1.280 + tmpAddress &= gbRomSizeMask; 1.281 + gbDataMBC3.mapperROMBank = value; 1.282 + gbMemoryMap[0x04] = &gbRom[tmpAddress]; 1.283 + gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; 1.284 + gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; 1.285 + gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; 1.286 + 1.287 + break; 1.288 + case 0x4000: // RAM bank select 1.289 + if (value < 8) 1.290 + { 1.291 + if (value == gbDataMBC3.mapperRAMBank) 1.292 + break; 1.293 + tmpAddress = value << 13; 1.294 + tmpAddress &= gbRamSizeMask; 1.295 + gbMemoryMap[0x0a] = &gbRam[tmpAddress]; 1.296 + gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000]; 1.297 + gbDataMBC3.mapperRAMBank = value; 1.298 + gbDataMBC3.mapperRAMAddress = tmpAddress; 1.299 + } 1.300 + else 1.301 + { 1.302 + if (gbDataMBC3.mapperRAMEnable) 1.303 + { 1.304 + gbDataMBC3.mapperRAMBank = -1; 1.305 + 1.306 + gbDataMBC3.mapperClockRegister = value; 1.307 + } 1.308 + } 1.309 + break; 1.310 + case 0x6000: // clock latch 1.311 + if (gbDataMBC3.mapperClockLatch == 0 && value == 1) 1.312 + { 1.313 + memoryUpdateMBC3Clock(); 1.314 + gbDataMBC3.mapperLSeconds = gbDataMBC3.mapperSeconds; 1.315 + gbDataMBC3.mapperLMinutes = gbDataMBC3.mapperMinutes; 1.316 + gbDataMBC3.mapperLHours = gbDataMBC3.mapperHours; 1.317 + gbDataMBC3.mapperLDays = gbDataMBC3.mapperDays; 1.318 + gbDataMBC3.mapperLControl = gbDataMBC3.mapperControl; 1.319 + } 1.320 + if (value == 0x00 || value == 0x01) 1.321 + gbDataMBC3.mapperClockLatch = value; 1.322 + break; 1.323 + } 1.324 +} 1.325 + 1.326 +// MBC3 RAM write 1.327 +void mapperMBC3RAM(u16 address, u8 value) 1.328 +{ 1.329 + if (gbDataMBC3.mapperRAMEnable) 1.330 + { 1.331 + if (gbDataMBC3.mapperRAMBank != -1) 1.332 + { 1.333 + if (gbRamSize) 1.334 + { 1.335 + gbWriteMemoryQuick(address, value); 1.336 + systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED; 1.337 + } 1.338 + } 1.339 + else 1.340 + { 1.341 + time_t tmp; //Small kludge to get it working on some 64 bit systems. 1.342 + if (VBAMovieActive() || VBAMovieLoading()) 1.343 + gbDataMBC3.mapperLastTime = VBAMovieGetId() + VBAMovieGetFrameCounter()/60; 1.344 + else { 1.345 + time(&tmp); 1.346 + gbDataMBC3.mapperLastTime=(u32)tmp; 1.347 + } 1.348 + systemScreenMessage(ctime(&tmp), 4); 1.349 + gbDataMBC3.mapperLastTime=(u32)tmp; 1.350 + 1.351 + switch (gbDataMBC3.mapperClockRegister) 1.352 + { 1.353 + case 0x08: 1.354 + gbDataMBC3.mapperSeconds = value; 1.355 + break; 1.356 + case 0x09: 1.357 + gbDataMBC3.mapperMinutes = value; 1.358 + break; 1.359 + case 0x0a: 1.360 + gbDataMBC3.mapperHours = value; 1.361 + break; 1.362 + case 0x0b: 1.363 + gbDataMBC3.mapperDays = value; 1.364 + break; 1.365 + case 0x0c: 1.366 + if (gbDataMBC3.mapperControl & 0x80) 1.367 + gbDataMBC3.mapperControl = 0x80 | value; 1.368 + else 1.369 + gbDataMBC3.mapperControl = value; 1.370 + break; 1.371 + } 1.372 + } 1.373 + } 1.374 +} 1.375 + 1.376 +// MBC3 read RAM 1.377 +u8 mapperMBC3ReadRAM(u16 address) 1.378 +{ 1.379 + if (gbDataMBC3.mapperRAMEnable) 1.380 + { 1.381 + if (gbDataMBC3.mapperRAMBank != -1) 1.382 + { 1.383 + return gbReadMemoryQuick(address); 1.384 + } 1.385 + 1.386 + switch (gbDataMBC3.mapperClockRegister) 1.387 + { 1.388 + case 0x08: 1.389 + return gbDataMBC3.mapperLSeconds; 1.390 + break; 1.391 + case 0x09: 1.392 + return gbDataMBC3.mapperLMinutes; 1.393 + break; 1.394 + case 0x0a: 1.395 + return gbDataMBC3.mapperLHours; 1.396 + break; 1.397 + case 0x0b: 1.398 + return gbDataMBC3.mapperLDays; 1.399 + break; 1.400 + case 0x0c: 1.401 + return gbDataMBC3.mapperLControl; 1.402 + } 1.403 + } 1.404 + return 0; 1.405 +} 1.406 + 1.407 +void memoryUpdateMapMBC3() 1.408 +{ 1.409 + int tmpAddress = gbDataMBC3.mapperROMBank << 14; 1.410 + 1.411 + tmpAddress &= gbRomSizeMask; 1.412 + 1.413 + gbMemoryMap[0x04] = &gbRom[tmpAddress]; 1.414 + gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; 1.415 + gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; 1.416 + gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; 1.417 + 1.418 + if (gbDataMBC3.mapperRAMBank >= 0 && gbRamSize) 1.419 + { 1.420 + tmpAddress = gbDataMBC3.mapperRAMBank << 13; 1.421 + tmpAddress &= gbRamSizeMask; 1.422 + gbMemoryMap[0x0a] = &gbRam[tmpAddress]; 1.423 + gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000]; 1.424 + } 1.425 +} 1.426 + 1.427 +mapperMBC5 gbDataMBC5 = { 1.428 + 0, // RAM enable 1.429 + 1, // ROM bank 1.430 + 0, // RAM bank 1.431 + 0, // ROM high address 1.432 + 0, // RAM address 1.433 + 0 // is rumble cartridge? 1.434 +}; 1.435 + 1.436 +// MBC5 ROM write registers 1.437 +void mapperMBC5ROM(u16 address, u8 value) 1.438 +{ 1.439 + int tmpAddress = 0; 1.440 + 1.441 + switch (address & 0x6000) 1.442 + { 1.443 + case 0x0000: // RAM enable register 1.444 + gbDataMBC5.mapperRAMEnable = ((value & 0x0a) == 0x0a ? 1 : 0); 1.445 + break; 1.446 + case 0x2000: // ROM bank select 1.447 + if (address < 0x3000) 1.448 + { 1.449 + value = value & 0xff; 1.450 + if (value == gbDataMBC5.mapperROMBank) 1.451 + break; 1.452 + 1.453 + tmpAddress = (value << 14) | (gbDataMBC5.mapperROMHighAddress << 22) ; 1.454 + 1.455 + tmpAddress &= gbRomSizeMask; 1.456 + gbDataMBC5.mapperROMBank = value; 1.457 + gbMemoryMap[0x04] = &gbRom[tmpAddress]; 1.458 + gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; 1.459 + gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; 1.460 + gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; 1.461 + } 1.462 + else 1.463 + { 1.464 + value = value & 1; 1.465 + if (value == gbDataMBC5.mapperROMHighAddress) 1.466 + break; 1.467 + 1.468 + tmpAddress = (gbDataMBC5.mapperROMBank << 14) | (value << 22); 1.469 + 1.470 + tmpAddress &= gbRomSizeMask; 1.471 + gbDataMBC5.mapperROMHighAddress = value; 1.472 + gbMemoryMap[0x04] = &gbRom[tmpAddress]; 1.473 + gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; 1.474 + gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; 1.475 + gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; 1.476 + } 1.477 + break; 1.478 + case 0x4000: // RAM bank select 1.479 + if (gbDataMBC5.isRumbleCartridge) 1.480 + value &= 0x07; 1.481 + else 1.482 + value &= 0x0f; 1.483 + if (value == gbDataMBC5.mapperRAMBank) 1.484 + break; 1.485 + tmpAddress = value << 13; 1.486 + tmpAddress &= gbRamSizeMask; 1.487 + if (gbRamSize) 1.488 + { 1.489 + gbMemoryMap[0x0a] = &gbRam[tmpAddress]; 1.490 + gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000]; 1.491 + 1.492 + gbDataMBC5.mapperRAMBank = value; 1.493 + gbDataMBC5.mapperRAMAddress = tmpAddress; 1.494 + } 1.495 + break; 1.496 + } 1.497 +} 1.498 + 1.499 +// MBC5 RAM write 1.500 +void mapperMBC5RAM(u16 address, u8 value) 1.501 +{ 1.502 + if (gbDataMBC5.mapperRAMEnable) 1.503 + { 1.504 + if (gbRamSize) 1.505 + { 1.506 + gbWriteMemoryQuick(address, value); 1.507 + systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED; 1.508 + } 1.509 + } 1.510 +} 1.511 + 1.512 +void memoryUpdateMapMBC5() 1.513 +{ 1.514 + int tmpAddress = (gbDataMBC5.mapperROMBank << 14) | 1.515 + (gbDataMBC5.mapperROMHighAddress << 22) ; 1.516 + 1.517 + tmpAddress &= gbRomSizeMask; 1.518 + gbMemoryMap[0x04] = &gbRom[tmpAddress]; 1.519 + gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; 1.520 + gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; 1.521 + gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; 1.522 + 1.523 + if (gbRamSize) 1.524 + { 1.525 + tmpAddress = gbDataMBC5.mapperRAMBank << 13; 1.526 + tmpAddress &= gbRamSizeMask; 1.527 + gbMemoryMap[0x0a] = &gbRam[tmpAddress]; 1.528 + gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000]; 1.529 + } 1.530 +} 1.531 + 1.532 +mapperMBC7 gbDataMBC7 = { 1.533 + 0, // RAM enable 1.534 + 1, // ROM bank 1.535 + 0, // RAM bank 1.536 + 0, // RAM address 1.537 + 0, // chip select 1.538 + 0, // ?? 1.539 + 0, // mapper state 1.540 + 0, // buffer for receiving serial data 1.541 + 0, // idle state 1.542 + 0, // count of bits received 1.543 + 0, // command received 1.544 + 0, // address received 1.545 + 0, // write enable 1.546 + 0, // value to return on ram 1.547 +}; 1.548 + 1.549 +// MBC7 ROM write registers 1.550 +void mapperMBC7ROM(u16 address, u8 value) 1.551 +{ 1.552 + int tmpAddress = 0; 1.553 + 1.554 + switch (address & 0x6000) 1.555 + { 1.556 + case 0x0000: 1.557 + break; 1.558 + case 0x2000: // ROM bank select 1.559 + value = value & 0x7f; 1.560 + if (value == 0) 1.561 + value = 1; 1.562 + 1.563 + if (value == gbDataMBC7.mapperROMBank) 1.564 + break; 1.565 + 1.566 + tmpAddress = (value << 14); 1.567 + 1.568 + tmpAddress &= gbRomSizeMask; 1.569 + gbDataMBC7.mapperROMBank = value; 1.570 + gbMemoryMap[0x04] = &gbRom[tmpAddress]; 1.571 + gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; 1.572 + gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; 1.573 + gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; 1.574 + break; 1.575 + case 0x4000: // RAM bank select/enable 1.576 + if (value < 8) 1.577 + { 1.578 + tmpAddress = (value&3) << 13; 1.579 + tmpAddress &= gbRamSizeMask; 1.580 + gbMemoryMap[0x0a] = &gbMemory[0xa000]; 1.581 + gbMemoryMap[0x0b] = &gbMemory[0xb000]; 1.582 + 1.583 + gbDataMBC7.mapperRAMBank = value; 1.584 + gbDataMBC7.mapperRAMAddress = tmpAddress; 1.585 + gbDataMBC7.mapperRAMEnable = 0; 1.586 + } 1.587 + else 1.588 + { 1.589 + gbDataMBC7.mapperRAMEnable = 0; 1.590 + } 1.591 + break; 1.592 + } 1.593 +} 1.594 + 1.595 +// MBC7 read RAM 1.596 +u8 mapperMBC7ReadRAM(u16 address) 1.597 +{ 1.598 + switch (address & 0xa0f0) 1.599 + { 1.600 + case 0xa000: 1.601 + case 0xa010: 1.602 + case 0xa060: 1.603 + case 0xa070: 1.604 + return 0; 1.605 + case 0xa020: 1.606 + // sensor X low byte 1.607 + return systemGetSensorX() & 255; 1.608 + case 0xa030: 1.609 + // sensor X high byte 1.610 + return systemGetSensorX() >> 8; 1.611 + case 0xa040: 1.612 + // sensor Y low byte 1.613 + return systemGetSensorY() & 255; 1.614 + case 0xa050: 1.615 + // sensor Y high byte 1.616 + return systemGetSensorY() >> 8; 1.617 + case 0xa080: 1.618 + return gbDataMBC7.value; 1.619 + } 1.620 + return 0xff; 1.621 +} 1.622 + 1.623 +// MBC7 RAM write 1.624 +void mapperMBC7RAM(u16 address, u8 value) 1.625 +{ 1.626 + if (address == 0xa080) 1.627 + { 1.628 + // special processing needed 1.629 + int oldCs = gbDataMBC7.cs, oldSk = gbDataMBC7.sk; 1.630 + 1.631 + gbDataMBC7.cs = value>>7; 1.632 + gbDataMBC7.sk = (value>>6)&1; 1.633 + 1.634 + if (!oldCs && gbDataMBC7.cs) 1.635 + { 1.636 + if (gbDataMBC7.state == 5) 1.637 + { 1.638 + if (gbDataMBC7.writeEnable) 1.639 + { 1.640 + gbWriteMemoryQuick(0xa000+gbDataMBC7.address*2, gbDataMBC7.buffer>>8); 1.641 + gbWriteMemoryQuick(0xa000+gbDataMBC7.address*2+1, gbDataMBC7.buffer&0xff); 1.642 + systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED; 1.643 + } 1.644 + gbDataMBC7.state = 0; 1.645 + gbDataMBC7.value = 1; 1.646 + } 1.647 + else 1.648 + { 1.649 + gbDataMBC7.idle = true; 1.650 + gbDataMBC7.state = 0; 1.651 + } 1.652 + } 1.653 + 1.654 + if (!oldSk && gbDataMBC7.sk) 1.655 + { 1.656 + if (gbDataMBC7.idle) 1.657 + { 1.658 + if (value & 0x02) 1.659 + { 1.660 + gbDataMBC7.idle = false; 1.661 + gbDataMBC7.count = 0; 1.662 + gbDataMBC7.state = 1; 1.663 + } 1.664 + } 1.665 + else 1.666 + { 1.667 + switch (gbDataMBC7.state) 1.668 + { 1.669 + case 1: 1.670 + // receiving command 1.671 + gbDataMBC7.buffer <<= 1; 1.672 + gbDataMBC7.buffer |= (value & 0x02) ? 1 : 0; 1.673 + gbDataMBC7.count++; 1.674 + if (gbDataMBC7.count == 2) 1.675 + { 1.676 + // finished receiving command 1.677 + gbDataMBC7.state = 2; 1.678 + gbDataMBC7.count = 0; 1.679 + gbDataMBC7.code = gbDataMBC7.buffer & 3; 1.680 + } 1.681 + break; 1.682 + case 2: 1.683 + // receive address 1.684 + gbDataMBC7.buffer <<= 1; 1.685 + gbDataMBC7.buffer |= (value&0x02) ? 1 : 0; 1.686 + gbDataMBC7.count++; 1.687 + if (gbDataMBC7.count == 8) 1.688 + { 1.689 + // finish receiving 1.690 + gbDataMBC7.state = 3; 1.691 + gbDataMBC7.count = 0; 1.692 + gbDataMBC7.address = gbDataMBC7.buffer&0xff; 1.693 + if (gbDataMBC7.code == 0) 1.694 + { 1.695 + if ((gbDataMBC7.address>>6) == 0) 1.696 + { 1.697 + gbDataMBC7.writeEnable = 0; 1.698 + gbDataMBC7.state = 0; 1.699 + } 1.700 + else if ((gbDataMBC7.address>>6) == 3) 1.701 + { 1.702 + gbDataMBC7.writeEnable = 1; 1.703 + gbDataMBC7.state = 0; 1.704 + } 1.705 + } 1.706 + } 1.707 + break; 1.708 + case 3: 1.709 + gbDataMBC7.buffer <<= 1; 1.710 + gbDataMBC7.buffer |= (value&0x02) ? 1 : 0; 1.711 + gbDataMBC7.count++; 1.712 + 1.713 + switch (gbDataMBC7.code) 1.714 + { 1.715 + case 0: 1.716 + if (gbDataMBC7.count == 16) 1.717 + { 1.718 + if ((gbDataMBC7.address>>6) == 0) 1.719 + { 1.720 + gbDataMBC7.writeEnable = 0; 1.721 + gbDataMBC7.state = 0; 1.722 + } 1.723 + else if ((gbDataMBC7.address>>6) == 1) 1.724 + { 1.725 + if (gbDataMBC7.writeEnable) 1.726 + { 1.727 + for (int i = 0; i < 256; i++) 1.728 + { 1.729 + gbWriteMemoryQuick(0xa000+i*2, gbDataMBC7.buffer >> 8); 1.730 + gbWriteMemoryQuick(0xa000+i*2+1, gbDataMBC7.buffer & 0xff); 1.731 + systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED; 1.732 + } 1.733 + } 1.734 + gbDataMBC7.state = 5; 1.735 + } 1.736 + else if ((gbDataMBC7.address>>6) == 2) 1.737 + { 1.738 + if (gbDataMBC7.writeEnable) 1.739 + { 1.740 + for (int i = 0; i < 256; i++) 1.741 + WRITE16LE((u16 *)&gbMemory[0xa000+i*2], 0xffff); 1.742 + systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED; 1.743 + } 1.744 + gbDataMBC7.state = 5; 1.745 + } 1.746 + else if ((gbDataMBC7.address>>6) == 3) 1.747 + { 1.748 + gbDataMBC7.writeEnable = 1; 1.749 + gbDataMBC7.state = 0; 1.750 + } 1.751 + gbDataMBC7.count = 0; 1.752 + } 1.753 + break; 1.754 + case 1: 1.755 + if (gbDataMBC7.count == 16) 1.756 + { 1.757 + gbDataMBC7.count = 0; 1.758 + gbDataMBC7.state = 5; 1.759 + gbDataMBC7.value = 0; 1.760 + } 1.761 + break; 1.762 + case 2: 1.763 + if (gbDataMBC7.count == 1) 1.764 + { 1.765 + gbDataMBC7.state = 4; 1.766 + gbDataMBC7.count = 0; 1.767 + gbDataMBC7.buffer = (gbReadMemoryQuick(0xa000+gbDataMBC7.address*2)<<8)| 1.768 + (gbReadMemoryQuick(0xa000+gbDataMBC7.address*2+1)); 1.769 + } 1.770 + break; 1.771 + case 3: 1.772 + if (gbDataMBC7.count == 16) 1.773 + { 1.774 + gbDataMBC7.count = 0; 1.775 + gbDataMBC7.state = 5; 1.776 + gbDataMBC7.value = 0; 1.777 + gbDataMBC7.buffer = 0xffff; 1.778 + } 1.779 + break; 1.780 + } 1.781 + break; 1.782 + } 1.783 + } 1.784 + } 1.785 + 1.786 + if (oldSk && !gbDataMBC7.sk) 1.787 + { 1.788 + if (gbDataMBC7.state == 4) 1.789 + { 1.790 + gbDataMBC7.value = (gbDataMBC7.buffer & 0x8000) ? 1 : 0; 1.791 + gbDataMBC7.buffer <<= 1; 1.792 + gbDataMBC7.count++; 1.793 + if (gbDataMBC7.count == 16) 1.794 + { 1.795 + gbDataMBC7.count = 0; 1.796 + gbDataMBC7.state = 0; 1.797 + } 1.798 + } 1.799 + } 1.800 + } 1.801 +} 1.802 + 1.803 +void memoryUpdateMapMBC7() 1.804 +{ 1.805 + int tmpAddress = (gbDataMBC5.mapperROMBank << 14); 1.806 + 1.807 + tmpAddress &= gbRomSizeMask; 1.808 + gbMemoryMap[0x04] = &gbRom[tmpAddress]; 1.809 + gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; 1.810 + gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; 1.811 + gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; 1.812 +} 1.813 + 1.814 +mapperHuC1 gbDataHuC1 = { 1.815 + 0, // RAM enable 1.816 + 1, // ROM bank 1.817 + 0, // RAM bank 1.818 + 0, // memory model 1.819 + 0, // ROM high address 1.820 + 0 // RAM address 1.821 +}; 1.822 + 1.823 +// HuC1 ROM write registers 1.824 +void mapperHuC1ROM(u16 address, u8 value) 1.825 +{ 1.826 + int tmpAddress = 0; 1.827 + 1.828 + switch (address & 0x6000) 1.829 + { 1.830 + case 0x0000: // RAM enable register 1.831 + gbDataHuC1.mapperRAMEnable = ((value & 0x0a) == 0x0a ? 1 : 0); 1.832 + break; 1.833 + case 0x2000: // ROM bank select 1.834 + value = value & 0x3f; 1.835 + if (value == 0) 1.836 + value = 1; 1.837 + if (value == gbDataHuC1.mapperROMBank) 1.838 + break; 1.839 + 1.840 + tmpAddress = value << 14; 1.841 + 1.842 + tmpAddress &= gbRomSizeMask; 1.843 + gbDataHuC1.mapperROMBank = value; 1.844 + gbMemoryMap[0x04] = &gbRom[tmpAddress]; 1.845 + gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; 1.846 + gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; 1.847 + gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; 1.848 + break; 1.849 + case 0x4000: // RAM bank select 1.850 + if (gbDataHuC1.mapperMemoryModel == 1) 1.851 + { 1.852 + // 4/32 model, RAM bank switching provided 1.853 + value = value & 0x03; 1.854 + if (value == gbDataHuC1.mapperRAMBank) 1.855 + break; 1.856 + tmpAddress = value << 13; 1.857 + tmpAddress &= gbRamSizeMask; 1.858 + gbMemoryMap[0x0a] = &gbRam[tmpAddress]; 1.859 + gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000]; 1.860 + gbDataHuC1.mapperRAMBank = value; 1.861 + gbDataHuC1.mapperRAMAddress = tmpAddress; 1.862 + } 1.863 + else 1.864 + { 1.865 + // 16/8, set the high address 1.866 + gbDataHuC1.mapperROMHighAddress = value & 0x03; 1.867 + tmpAddress = gbDataHuC1.mapperROMBank << 14; 1.868 + tmpAddress |= (gbDataHuC1.mapperROMHighAddress) << 19; 1.869 + tmpAddress &= gbRomSizeMask; 1.870 + gbMemoryMap[0x04] = &gbRom[tmpAddress]; 1.871 + gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; 1.872 + gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; 1.873 + gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; 1.874 + } 1.875 + break; 1.876 + case 0x6000: // memory model select 1.877 + gbDataHuC1.mapperMemoryModel = value & 1; 1.878 + break; 1.879 + } 1.880 +} 1.881 + 1.882 +// HuC1 RAM write 1.883 +void mapperHuC1RAM(u16 address, u8 value) 1.884 +{ 1.885 + if (gbDataHuC1.mapperRAMEnable) 1.886 + { 1.887 + if (gbRamSize) 1.888 + { 1.889 + gbWriteMemoryQuick(address, value); 1.890 + systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED; 1.891 + } 1.892 + } 1.893 +} 1.894 + 1.895 +void memoryUpdateMapHuC1() 1.896 +{ 1.897 + int tmpAddress = gbDataHuC1.mapperROMBank << 14; 1.898 + 1.899 + tmpAddress &= gbRomSizeMask; 1.900 + 1.901 + gbMemoryMap[0x04] = &gbRom[tmpAddress]; 1.902 + gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; 1.903 + gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; 1.904 + gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; 1.905 + 1.906 + if (gbRamSize) 1.907 + { 1.908 + tmpAddress = gbDataHuC1.mapperRAMBank << 13; 1.909 + tmpAddress &= gbRamSizeMask; 1.910 + gbMemoryMap[0x0a] = &gbRam[tmpAddress]; 1.911 + gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000]; 1.912 + } 1.913 +} 1.914 + 1.915 +mapperHuC3 gbDataHuC3 = { 1.916 + 0, // RAM enable 1.917 + 1, // ROM bank 1.918 + 0, // RAM bank 1.919 + 0, // RAM address 1.920 + 0, // RAM flag 1.921 + 0 // RAM read value 1.922 +}; 1.923 + 1.924 +// HuC3 ROM write registers 1.925 +void mapperHuC3ROM(u16 address, u8 value) 1.926 +{ 1.927 + int tmpAddress = 0; 1.928 + 1.929 + switch (address & 0x6000) 1.930 + { 1.931 + case 0x0000: // RAM enable register 1.932 + gbDataHuC3.mapperRAMEnable = (value == 0x0a ? 1 : 0); 1.933 + gbDataHuC3.mapperRAMFlag = value; 1.934 + if (gbDataHuC3.mapperRAMFlag != 0x0a) 1.935 + gbDataHuC3.mapperRAMBank = -1; 1.936 + break; 1.937 + case 0x2000: // ROM bank select 1.938 + value = value & 0x7f; 1.939 + if (value == 0) 1.940 + value = 1; 1.941 + if (value == gbDataHuC3.mapperROMBank) 1.942 + break; 1.943 + 1.944 + tmpAddress = value << 14; 1.945 + 1.946 + tmpAddress &= gbRomSizeMask; 1.947 + gbDataHuC3.mapperROMBank = value; 1.948 + gbMemoryMap[0x04] = &gbRom[tmpAddress]; 1.949 + gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; 1.950 + gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; 1.951 + gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; 1.952 + break; 1.953 + case 0x4000: // RAM bank select 1.954 + value = value & 0x03; 1.955 + if (value == gbDataHuC3.mapperRAMBank) 1.956 + break; 1.957 + tmpAddress = value << 13; 1.958 + tmpAddress &= gbRamSizeMask; 1.959 + gbMemoryMap[0x0a] = &gbRam[tmpAddress]; 1.960 + gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000]; 1.961 + gbDataHuC3.mapperRAMBank = value; 1.962 + gbDataHuC3.mapperRAMAddress = tmpAddress; 1.963 + break; 1.964 + case 0x6000: // nothing to do! 1.965 + break; 1.966 + } 1.967 +} 1.968 + 1.969 +// HuC3 read RAM 1.970 +u8 mapperHuC3ReadRAM(u16 address) 1.971 +{ 1.972 + if (gbDataHuC3.mapperRAMFlag > 0x0b && 1.973 + gbDataHuC3.mapperRAMFlag < 0x0e) 1.974 + { 1.975 + if (gbDataHuC3.mapperRAMFlag != 0x0c) 1.976 + return 1; 1.977 + return gbDataHuC3.mapperRAMValue; 1.978 + } 1.979 + else 1.980 + return gbReadMemoryQuick(address); 1.981 +} 1.982 + 1.983 +// HuC3 RAM write 1.984 +void mapperHuC3RAM(u16 address, u8 value) 1.985 +{ 1.986 + int32 *p; 1.987 + 1.988 + if (gbDataHuC3.mapperRAMFlag < 0x0b || 1.989 + gbDataHuC3.mapperRAMFlag > 0x0e) 1.990 + { 1.991 + if (gbDataHuC3.mapperRAMEnable) 1.992 + { 1.993 + if (gbRamSize) 1.994 + { 1.995 + gbWriteMemoryQuick(address, value); 1.996 + systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED; 1.997 + } 1.998 + } 1.999 + } 1.1000 + else 1.1001 + { 1.1002 + if (gbDataHuC3.mapperRAMFlag == 0x0b) 1.1003 + { 1.1004 + if (value == 0x62) 1.1005 + { 1.1006 + gbDataHuC3.mapperRAMValue = 1; 1.1007 + } 1.1008 + else 1.1009 + { 1.1010 + switch (value & 0xf0) 1.1011 + { 1.1012 + case 0x10: 1.1013 + p = &gbDataHuC3.mapperRegister2; 1.1014 + gbDataHuC3.mapperRAMValue = *(p+gbDataHuC3.mapperRegister1++); 1.1015 + if (gbDataHuC3.mapperRegister1 > 6) 1.1016 + gbDataHuC3.mapperRegister1 = 0; 1.1017 + break; 1.1018 + case 0x30: 1.1019 + p = &gbDataHuC3.mapperRegister2; 1.1020 + *(p+gbDataHuC3.mapperRegister1++) = value & 0x0f; 1.1021 + if (gbDataHuC3.mapperRegister1 > 6) 1.1022 + gbDataHuC3.mapperRegister1 = 0; 1.1023 + gbDataHuC3.mapperAddress = 1.1024 + (gbDataHuC3.mapperRegister6 << 24) | 1.1025 + (gbDataHuC3.mapperRegister5 << 16) | 1.1026 + (gbDataHuC3.mapperRegister4 << 8) | 1.1027 + (gbDataHuC3.mapperRegister3 << 4) | 1.1028 + (gbDataHuC3.mapperRegister2); 1.1029 + break; 1.1030 + case 0x40: 1.1031 + gbDataHuC3.mapperRegister1 = (gbDataHuC3.mapperRegister1 & 0xf0) | 1.1032 + (value & 0x0f); 1.1033 + gbDataHuC3.mapperRegister2 = (gbDataHuC3.mapperAddress & 0x0f); 1.1034 + gbDataHuC3.mapperRegister3 = ((gbDataHuC3.mapperAddress>>4)&0x0f); 1.1035 + gbDataHuC3.mapperRegister4 = ((gbDataHuC3.mapperAddress>>8)&0x0f); 1.1036 + gbDataHuC3.mapperRegister5 = ((gbDataHuC3.mapperAddress>>16)&0x0f); 1.1037 + gbDataHuC3.mapperRegister6 = ((gbDataHuC3.mapperAddress>>24)&0x0f); 1.1038 + gbDataHuC3.mapperRegister7 = 0; 1.1039 + gbDataHuC3.mapperRegister8 = 0; 1.1040 + gbDataHuC3.mapperRAMValue = 0; 1.1041 + break; 1.1042 + case 0x50: 1.1043 + gbDataHuC3.mapperRegister1 = (gbDataHuC3.mapperRegister1 & 0x0f) | 1.1044 + ((value << 4)&0x0f); 1.1045 + break; 1.1046 + default: 1.1047 + gbDataHuC3.mapperRAMValue = 1; 1.1048 + break; 1.1049 + } 1.1050 + } 1.1051 + } 1.1052 + } 1.1053 +} 1.1054 + 1.1055 +void memoryUpdateMapHuC3() 1.1056 +{ 1.1057 + int tmpAddress = gbDataHuC3.mapperROMBank << 14; 1.1058 + 1.1059 + tmpAddress &= gbRomSizeMask; 1.1060 + gbMemoryMap[0x04] = &gbRom[tmpAddress]; 1.1061 + gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; 1.1062 + gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; 1.1063 + gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; 1.1064 + 1.1065 + if (gbRamSize) 1.1066 + { 1.1067 + tmpAddress = gbDataHuC3.mapperRAMBank << 13; 1.1068 + tmpAddress &= gbRamSizeMask; 1.1069 + gbMemoryMap[0x0a] = &gbRam[tmpAddress]; 1.1070 + gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000]; 1.1071 + } 1.1072 +} 1.1073 +