annotate src/gb/gbMemory.cpp @ 551:b69a3dba8045

condensed gameboy program into a contigous sequence of bytes.
author Robert McIntyre <rlm@mit.edu>
date Thu, 30 Aug 2012 11:19:52 -0500
parents f9f4f1b99eed
children
rev   line source
rlm@1 1 #include "gbGlobals.h"
rlm@1 2 #include "gbMemory.h"
rlm@1 3 #include "../common/System.h"
rlm@1 4 #include "../common/movie.h"
rlm@1 5
rlm@1 6 mapperMBC1 gbDataMBC1 = {
rlm@1 7 0, // RAM enable
rlm@1 8 1, // ROM bank
rlm@1 9 0, // RAM bank
rlm@1 10 0, // memory model
rlm@1 11 0, // ROM high address
rlm@1 12 0 // RAM address
rlm@1 13 };
rlm@1 14
rlm@1 15 // MBC1 ROM write registers
rlm@1 16 void mapperMBC1ROM(u16 address, u8 value)
rlm@1 17 {
rlm@1 18 int tmpAddress = 0;
rlm@1 19
rlm@1 20 switch (address & 0x6000)
rlm@1 21 {
rlm@1 22 case 0x0000: // RAM enable register
rlm@1 23 gbDataMBC1.mapperRAMEnable = ((value & 0x0a) == 0x0a ? 1 : 0);
rlm@1 24 break;
rlm@1 25 case 0x2000: // ROM bank select
rlm@1 26 // value = value & 0x1f;
rlm@1 27 if (value == 0)
rlm@1 28 value = 1;
rlm@1 29 if (value == gbDataMBC1.mapperROMBank)
rlm@1 30 break;
rlm@1 31
rlm@1 32 tmpAddress = value << 14;
rlm@1 33
rlm@1 34 // check current model
rlm@1 35 if (gbDataMBC1.mapperMemoryModel == 0)
rlm@1 36 {
rlm@1 37 // model is 16/8, so we have a high address in use
rlm@1 38 tmpAddress |= (gbDataMBC1.mapperROMHighAddress) << 19;
rlm@1 39 }
rlm@1 40
rlm@1 41 tmpAddress &= gbRomSizeMask;
rlm@1 42 gbDataMBC1.mapperROMBank = value;
rlm@1 43 gbMemoryMap[0x04] = &gbRom[tmpAddress];
rlm@1 44 gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
rlm@1 45 gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
rlm@1 46 gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
rlm@1 47 break;
rlm@1 48 case 0x4000: // RAM bank select
rlm@1 49 if (gbDataMBC1.mapperMemoryModel == 1)
rlm@1 50 {
rlm@1 51 // 4/32 model, RAM bank switching provided
rlm@1 52 value = value & 0x03;
rlm@1 53 if (value == gbDataMBC1.mapperRAMBank)
rlm@1 54 break;
rlm@1 55 tmpAddress = value << 13;
rlm@1 56 tmpAddress &= gbRamSizeMask;
rlm@1 57 gbMemoryMap[0x0a] = &gbRam[tmpAddress];
rlm@1 58 gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000];
rlm@1 59 gbDataMBC1.mapperRAMBank = value;
rlm@1 60 gbDataMBC1.mapperRAMAddress = tmpAddress;
rlm@1 61 }
rlm@1 62 else
rlm@1 63 {
rlm@1 64 // 16/8, set the high address
rlm@1 65 gbDataMBC1.mapperROMHighAddress = value & 0x03;
rlm@1 66 tmpAddress = gbDataMBC1.mapperROMBank << 14;
rlm@1 67 tmpAddress |= (gbDataMBC1.mapperROMHighAddress) << 19;
rlm@1 68 tmpAddress &= gbRomSizeMask;
rlm@1 69 gbMemoryMap[0x04] = &gbRom[tmpAddress];
rlm@1 70 gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
rlm@1 71 gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
rlm@1 72 gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
rlm@1 73 }
rlm@1 74 break;
rlm@1 75 case 0x6000: // memory model select
rlm@1 76 gbDataMBC1.mapperMemoryModel = value & 1;
rlm@1 77 break;
rlm@1 78 }
rlm@1 79 }
rlm@1 80
rlm@1 81 // MBC1 RAM write
rlm@1 82 void mapperMBC1RAM(u16 address, u8 value)
rlm@1 83 {
rlm@1 84 if (gbDataMBC1.mapperRAMEnable)
rlm@1 85 {
rlm@1 86 if (gbRamSize)
rlm@1 87 {
rlm@1 88 gbWriteMemoryQuick(address, value);
rlm@1 89 systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED;
rlm@1 90 }
rlm@1 91 }
rlm@1 92 }
rlm@1 93
rlm@1 94 void memoryUpdateMapMBC1()
rlm@1 95 {
rlm@1 96 int tmpAddress = gbDataMBC1.mapperROMBank << 14;
rlm@1 97
rlm@1 98 // check current model
rlm@1 99 if (gbDataMBC1.mapperMemoryModel == 1)
rlm@1 100 {
rlm@1 101 // model is 16/8, so we have a high address in use
rlm@1 102 tmpAddress |= (gbDataMBC1.mapperROMHighAddress) << 19;
rlm@1 103 }
rlm@1 104
rlm@1 105 tmpAddress &= gbRomSizeMask;
rlm@1 106 gbMemoryMap[0x04] = &gbRom[tmpAddress];
rlm@1 107 gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
rlm@1 108 gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
rlm@1 109 gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
rlm@1 110
rlm@1 111 if (gbRamSize)
rlm@1 112 {
rlm@1 113 gbMemoryMap[0x0a] = &gbRam[gbDataMBC1.mapperRAMAddress];
rlm@1 114 gbMemoryMap[0x0b] = &gbRam[gbDataMBC1.mapperRAMAddress + 0x1000];
rlm@1 115 }
rlm@1 116 }
rlm@1 117
rlm@1 118 mapperMBC2 gbDataMBC2 = {
rlm@1 119 0, // RAM enable
rlm@1 120 1 // ROM bank
rlm@1 121 };
rlm@1 122
rlm@1 123 // MBC2 ROM write registers
rlm@1 124 void mapperMBC2ROM(u16 address, u8 value)
rlm@1 125 {
rlm@1 126 switch (address & 0x6000)
rlm@1 127 {
rlm@1 128 case 0x0000: // RAM enable
rlm@1 129 if (!(address & 0x0100))
rlm@1 130 {
rlm@1 131 gbDataMBC2.mapperRAMEnable = (value & 0x0f) == 0x0a;
rlm@1 132 }
rlm@1 133 break;
rlm@1 134 case 0x2000: // ROM bank select
rlm@1 135 if (address & 0x0100)
rlm@1 136 {
rlm@1 137 value &= 0x0f;
rlm@1 138
rlm@1 139 if (value == 0)
rlm@1 140 value = 1;
rlm@1 141 if (gbDataMBC2.mapperROMBank != value)
rlm@1 142 {
rlm@1 143 gbDataMBC2.mapperROMBank = value;
rlm@1 144
rlm@1 145 int tmpAddress = value << 14;
rlm@1 146
rlm@1 147 tmpAddress &= gbRomSizeMask;
rlm@1 148
rlm@1 149 gbMemoryMap[0x04] = &gbRom[tmpAddress];
rlm@1 150 gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
rlm@1 151 gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
rlm@1 152 gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
rlm@1 153 }
rlm@1 154 }
rlm@1 155 break;
rlm@1 156 }
rlm@1 157 }
rlm@1 158
rlm@1 159 // MBC2 RAM write
rlm@1 160 void mapperMBC2RAM(u16 address, u8 value)
rlm@1 161 {
rlm@1 162 if (gbDataMBC2.mapperRAMEnable)
rlm@1 163 {
rlm@1 164 if (gbRamSize && address < 0xa200)
rlm@1 165 {
rlm@1 166 gbWriteMemoryQuick(address, value);
rlm@1 167 systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED;
rlm@1 168 }
rlm@1 169 }
rlm@1 170 }
rlm@1 171
rlm@1 172 void memoryUpdateMapMBC2()
rlm@1 173 {
rlm@1 174 int tmpAddress = gbDataMBC2.mapperROMBank << 14;
rlm@1 175
rlm@1 176 tmpAddress &= gbRomSizeMask;
rlm@1 177
rlm@1 178 gbMemoryMap[0x04] = &gbRom[tmpAddress];
rlm@1 179 gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
rlm@1 180 gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
rlm@1 181 gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
rlm@1 182 }
rlm@1 183
rlm@1 184 mapperMBC3 gbDataMBC3 = {
rlm@1 185 0, // RAM enable
rlm@1 186 1, // ROM bank
rlm@1 187 0, // RAM bank
rlm@1 188 0, // RAM address
rlm@1 189 0, // timer clock latch
rlm@1 190 0, // timer clock register
rlm@1 191 0, // timer seconds
rlm@1 192 0, // timer minutes
rlm@1 193 0, // timer hours
rlm@1 194 0, // timer days
rlm@1 195 0, // timer control
rlm@1 196 0, // timer latched seconds
rlm@1 197 0, // timer latched minutes
rlm@1 198 0, // timer latched hours
rlm@1 199 0, // timer latched days
rlm@1 200 0, // timer latched control
rlm@1 201 (time_t)-1 // last time
rlm@1 202 };
rlm@1 203
rlm@1 204 void memoryUpdateMBC3Clock()
rlm@1 205 {
rlm@1 206 time_t now;
rlm@1 207
rlm@1 208 if (VBAMovieActive() || VBAMovieLoading())
rlm@1 209 now = (time_t)(VBAMovieGetId() + VBAMovieGetFrameCounter()/60); /// FIXME: is /60 the right factor?
rlm@1 210 else
rlm@1 211 now = time(NULL);
rlm@1 212
rlm@1 213 time_t diff = now - gbDataMBC3.mapperLastTime;
rlm@1 214 if (diff > 0)
rlm@1 215 {
rlm@1 216 // update the clock according to the last update time
rlm@1 217 gbDataMBC3.mapperSeconds += (int)(diff % 60);
rlm@1 218 if (gbDataMBC3.mapperSeconds > 59)
rlm@1 219 {
rlm@1 220 gbDataMBC3.mapperSeconds -= 60;
rlm@1 221 gbDataMBC3.mapperMinutes++;
rlm@1 222 }
rlm@1 223
rlm@1 224 diff /= 60;
rlm@1 225
rlm@1 226 gbDataMBC3.mapperMinutes += (int)(diff % 60);
rlm@1 227 if (gbDataMBC3.mapperMinutes > 60)
rlm@1 228 {
rlm@1 229 gbDataMBC3.mapperMinutes -= 60;
rlm@1 230 gbDataMBC3.mapperHours++;
rlm@1 231 }
rlm@1 232
rlm@1 233 diff /= 60;
rlm@1 234
rlm@1 235 gbDataMBC3.mapperHours += (int)(diff % 24);
rlm@1 236 if (gbDataMBC3.mapperHours > 24)
rlm@1 237 {
rlm@1 238 gbDataMBC3.mapperHours -= 24;
rlm@1 239 gbDataMBC3.mapperDays++;
rlm@1 240 }
rlm@1 241 diff /= 24;
rlm@1 242
rlm@1 243 gbDataMBC3.mapperDays += (int)diff;
rlm@1 244 if (gbDataMBC3.mapperDays > 255)
rlm@1 245 {
rlm@1 246 if (gbDataMBC3.mapperDays > 511)
rlm@1 247 {
rlm@1 248 gbDataMBC3.mapperDays %= 512;
rlm@1 249 gbDataMBC3.mapperControl |= 0x80;
rlm@1 250 }
rlm@1 251 gbDataMBC3.mapperControl = (gbDataMBC3.mapperControl & 0xfe) |
rlm@1 252 (gbDataMBC3.mapperDays > 255 ? 1 : 0);
rlm@1 253 }
rlm@1 254 }
rlm@1 255 gbDataMBC3.mapperLastTime = now;
rlm@1 256 }
rlm@1 257
rlm@1 258 // MBC3 ROM write registers
rlm@1 259 void mapperMBC3ROM(u16 address, u8 value)
rlm@1 260 {
rlm@1 261 int tmpAddress = 0;
rlm@1 262
rlm@1 263 switch (address & 0x6000)
rlm@1 264 {
rlm@1 265 case 0x0000: // RAM enable register
rlm@1 266 gbDataMBC3.mapperRAMEnable = ((value & 0x0a) == 0x0a ? 1 : 0);
rlm@1 267 break;
rlm@1 268 case 0x2000: // ROM bank select
rlm@1 269 value = value & 0x7f;
rlm@1 270 if (value == 0)
rlm@1 271 value = 1;
rlm@1 272 if (value == gbDataMBC3.mapperROMBank)
rlm@1 273 break;
rlm@1 274
rlm@1 275 tmpAddress = value << 14;
rlm@1 276
rlm@1 277 tmpAddress &= gbRomSizeMask;
rlm@1 278 gbDataMBC3.mapperROMBank = value;
rlm@1 279 gbMemoryMap[0x04] = &gbRom[tmpAddress];
rlm@1 280 gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
rlm@1 281 gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
rlm@1 282 gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
rlm@1 283
rlm@1 284 break;
rlm@1 285 case 0x4000: // RAM bank select
rlm@1 286 if (value < 8)
rlm@1 287 {
rlm@1 288 if (value == gbDataMBC3.mapperRAMBank)
rlm@1 289 break;
rlm@1 290 tmpAddress = value << 13;
rlm@1 291 tmpAddress &= gbRamSizeMask;
rlm@1 292 gbMemoryMap[0x0a] = &gbRam[tmpAddress];
rlm@1 293 gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000];
rlm@1 294 gbDataMBC3.mapperRAMBank = value;
rlm@1 295 gbDataMBC3.mapperRAMAddress = tmpAddress;
rlm@1 296 }
rlm@1 297 else
rlm@1 298 {
rlm@1 299 if (gbDataMBC3.mapperRAMEnable)
rlm@1 300 {
rlm@1 301 gbDataMBC3.mapperRAMBank = -1;
rlm@1 302
rlm@1 303 gbDataMBC3.mapperClockRegister = value;
rlm@1 304 }
rlm@1 305 }
rlm@1 306 break;
rlm@1 307 case 0x6000: // clock latch
rlm@1 308 if (gbDataMBC3.mapperClockLatch == 0 && value == 1)
rlm@1 309 {
rlm@1 310 memoryUpdateMBC3Clock();
rlm@1 311 gbDataMBC3.mapperLSeconds = gbDataMBC3.mapperSeconds;
rlm@1 312 gbDataMBC3.mapperLMinutes = gbDataMBC3.mapperMinutes;
rlm@1 313 gbDataMBC3.mapperLHours = gbDataMBC3.mapperHours;
rlm@1 314 gbDataMBC3.mapperLDays = gbDataMBC3.mapperDays;
rlm@1 315 gbDataMBC3.mapperLControl = gbDataMBC3.mapperControl;
rlm@1 316 }
rlm@1 317 if (value == 0x00 || value == 0x01)
rlm@1 318 gbDataMBC3.mapperClockLatch = value;
rlm@1 319 break;
rlm@1 320 }
rlm@1 321 }
rlm@1 322
rlm@1 323 // MBC3 RAM write
rlm@1 324 void mapperMBC3RAM(u16 address, u8 value)
rlm@1 325 {
rlm@1 326 if (gbDataMBC3.mapperRAMEnable)
rlm@1 327 {
rlm@1 328 if (gbDataMBC3.mapperRAMBank != -1)
rlm@1 329 {
rlm@1 330 if (gbRamSize)
rlm@1 331 {
rlm@1 332 gbWriteMemoryQuick(address, value);
rlm@1 333 systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED;
rlm@1 334 }
rlm@1 335 }
rlm@1 336 else
rlm@1 337 {
rlm@1 338 time_t tmp; //Small kludge to get it working on some 64 bit systems.
rlm@1 339 if (VBAMovieActive() || VBAMovieLoading())
rlm@1 340 gbDataMBC3.mapperLastTime = VBAMovieGetId() + VBAMovieGetFrameCounter()/60;
rlm@1 341 else {
rlm@1 342 time(&tmp);
rlm@1 343 gbDataMBC3.mapperLastTime=(u32)tmp;
rlm@1 344 }
rlm@1 345 systemScreenMessage(ctime(&tmp), 4);
rlm@1 346 gbDataMBC3.mapperLastTime=(u32)tmp;
rlm@1 347
rlm@1 348 switch (gbDataMBC3.mapperClockRegister)
rlm@1 349 {
rlm@1 350 case 0x08:
rlm@1 351 gbDataMBC3.mapperSeconds = value;
rlm@1 352 break;
rlm@1 353 case 0x09:
rlm@1 354 gbDataMBC3.mapperMinutes = value;
rlm@1 355 break;
rlm@1 356 case 0x0a:
rlm@1 357 gbDataMBC3.mapperHours = value;
rlm@1 358 break;
rlm@1 359 case 0x0b:
rlm@1 360 gbDataMBC3.mapperDays = value;
rlm@1 361 break;
rlm@1 362 case 0x0c:
rlm@1 363 if (gbDataMBC3.mapperControl & 0x80)
rlm@1 364 gbDataMBC3.mapperControl = 0x80 | value;
rlm@1 365 else
rlm@1 366 gbDataMBC3.mapperControl = value;
rlm@1 367 break;
rlm@1 368 }
rlm@1 369 }
rlm@1 370 }
rlm@1 371 }
rlm@1 372
rlm@1 373 // MBC3 read RAM
rlm@1 374 u8 mapperMBC3ReadRAM(u16 address)
rlm@1 375 {
rlm@1 376 if (gbDataMBC3.mapperRAMEnable)
rlm@1 377 {
rlm@1 378 if (gbDataMBC3.mapperRAMBank != -1)
rlm@1 379 {
rlm@1 380 return gbReadMemoryQuick(address);
rlm@1 381 }
rlm@1 382
rlm@1 383 switch (gbDataMBC3.mapperClockRegister)
rlm@1 384 {
rlm@1 385 case 0x08:
rlm@1 386 return gbDataMBC3.mapperLSeconds;
rlm@1 387 break;
rlm@1 388 case 0x09:
rlm@1 389 return gbDataMBC3.mapperLMinutes;
rlm@1 390 break;
rlm@1 391 case 0x0a:
rlm@1 392 return gbDataMBC3.mapperLHours;
rlm@1 393 break;
rlm@1 394 case 0x0b:
rlm@1 395 return gbDataMBC3.mapperLDays;
rlm@1 396 break;
rlm@1 397 case 0x0c:
rlm@1 398 return gbDataMBC3.mapperLControl;
rlm@1 399 }
rlm@1 400 }
rlm@1 401 return 0;
rlm@1 402 }
rlm@1 403
rlm@1 404 void memoryUpdateMapMBC3()
rlm@1 405 {
rlm@1 406 int tmpAddress = gbDataMBC3.mapperROMBank << 14;
rlm@1 407
rlm@1 408 tmpAddress &= gbRomSizeMask;
rlm@1 409
rlm@1 410 gbMemoryMap[0x04] = &gbRom[tmpAddress];
rlm@1 411 gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
rlm@1 412 gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
rlm@1 413 gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
rlm@1 414
rlm@1 415 if (gbDataMBC3.mapperRAMBank >= 0 && gbRamSize)
rlm@1 416 {
rlm@1 417 tmpAddress = gbDataMBC3.mapperRAMBank << 13;
rlm@1 418 tmpAddress &= gbRamSizeMask;
rlm@1 419 gbMemoryMap[0x0a] = &gbRam[tmpAddress];
rlm@1 420 gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000];
rlm@1 421 }
rlm@1 422 }
rlm@1 423
rlm@1 424 mapperMBC5 gbDataMBC5 = {
rlm@1 425 0, // RAM enable
rlm@1 426 1, // ROM bank
rlm@1 427 0, // RAM bank
rlm@1 428 0, // ROM high address
rlm@1 429 0, // RAM address
rlm@1 430 0 // is rumble cartridge?
rlm@1 431 };
rlm@1 432
rlm@1 433 // MBC5 ROM write registers
rlm@1 434 void mapperMBC5ROM(u16 address, u8 value)
rlm@1 435 {
rlm@1 436 int tmpAddress = 0;
rlm@1 437
rlm@1 438 switch (address & 0x6000)
rlm@1 439 {
rlm@1 440 case 0x0000: // RAM enable register
rlm@1 441 gbDataMBC5.mapperRAMEnable = ((value & 0x0a) == 0x0a ? 1 : 0);
rlm@1 442 break;
rlm@1 443 case 0x2000: // ROM bank select
rlm@1 444 if (address < 0x3000)
rlm@1 445 {
rlm@1 446 value = value & 0xff;
rlm@1 447 if (value == gbDataMBC5.mapperROMBank)
rlm@1 448 break;
rlm@1 449
rlm@1 450 tmpAddress = (value << 14) | (gbDataMBC5.mapperROMHighAddress << 22) ;
rlm@1 451
rlm@1 452 tmpAddress &= gbRomSizeMask;
rlm@1 453 gbDataMBC5.mapperROMBank = value;
rlm@1 454 gbMemoryMap[0x04] = &gbRom[tmpAddress];
rlm@1 455 gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
rlm@1 456 gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
rlm@1 457 gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
rlm@1 458 }
rlm@1 459 else
rlm@1 460 {
rlm@1 461 value = value & 1;
rlm@1 462 if (value == gbDataMBC5.mapperROMHighAddress)
rlm@1 463 break;
rlm@1 464
rlm@1 465 tmpAddress = (gbDataMBC5.mapperROMBank << 14) | (value << 22);
rlm@1 466
rlm@1 467 tmpAddress &= gbRomSizeMask;
rlm@1 468 gbDataMBC5.mapperROMHighAddress = value;
rlm@1 469 gbMemoryMap[0x04] = &gbRom[tmpAddress];
rlm@1 470 gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
rlm@1 471 gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
rlm@1 472 gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
rlm@1 473 }
rlm@1 474 break;
rlm@1 475 case 0x4000: // RAM bank select
rlm@1 476 if (gbDataMBC5.isRumbleCartridge)
rlm@1 477 value &= 0x07;
rlm@1 478 else
rlm@1 479 value &= 0x0f;
rlm@1 480 if (value == gbDataMBC5.mapperRAMBank)
rlm@1 481 break;
rlm@1 482 tmpAddress = value << 13;
rlm@1 483 tmpAddress &= gbRamSizeMask;
rlm@1 484 if (gbRamSize)
rlm@1 485 {
rlm@1 486 gbMemoryMap[0x0a] = &gbRam[tmpAddress];
rlm@1 487 gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000];
rlm@1 488
rlm@1 489 gbDataMBC5.mapperRAMBank = value;
rlm@1 490 gbDataMBC5.mapperRAMAddress = tmpAddress;
rlm@1 491 }
rlm@1 492 break;
rlm@1 493 }
rlm@1 494 }
rlm@1 495
rlm@1 496 // MBC5 RAM write
rlm@1 497 void mapperMBC5RAM(u16 address, u8 value)
rlm@1 498 {
rlm@1 499 if (gbDataMBC5.mapperRAMEnable)
rlm@1 500 {
rlm@1 501 if (gbRamSize)
rlm@1 502 {
rlm@1 503 gbWriteMemoryQuick(address, value);
rlm@1 504 systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED;
rlm@1 505 }
rlm@1 506 }
rlm@1 507 }
rlm@1 508
rlm@1 509 void memoryUpdateMapMBC5()
rlm@1 510 {
rlm@1 511 int tmpAddress = (gbDataMBC5.mapperROMBank << 14) |
rlm@1 512 (gbDataMBC5.mapperROMHighAddress << 22) ;
rlm@1 513
rlm@1 514 tmpAddress &= gbRomSizeMask;
rlm@1 515 gbMemoryMap[0x04] = &gbRom[tmpAddress];
rlm@1 516 gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
rlm@1 517 gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
rlm@1 518 gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
rlm@1 519
rlm@1 520 if (gbRamSize)
rlm@1 521 {
rlm@1 522 tmpAddress = gbDataMBC5.mapperRAMBank << 13;
rlm@1 523 tmpAddress &= gbRamSizeMask;
rlm@1 524 gbMemoryMap[0x0a] = &gbRam[tmpAddress];
rlm@1 525 gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000];
rlm@1 526 }
rlm@1 527 }
rlm@1 528
rlm@1 529 mapperMBC7 gbDataMBC7 = {
rlm@1 530 0, // RAM enable
rlm@1 531 1, // ROM bank
rlm@1 532 0, // RAM bank
rlm@1 533 0, // RAM address
rlm@1 534 0, // chip select
rlm@1 535 0, // ??
rlm@1 536 0, // mapper state
rlm@1 537 0, // buffer for receiving serial data
rlm@1 538 0, // idle state
rlm@1 539 0, // count of bits received
rlm@1 540 0, // command received
rlm@1 541 0, // address received
rlm@1 542 0, // write enable
rlm@1 543 0, // value to return on ram
rlm@1 544 };
rlm@1 545
rlm@1 546 // MBC7 ROM write registers
rlm@1 547 void mapperMBC7ROM(u16 address, u8 value)
rlm@1 548 {
rlm@1 549 int tmpAddress = 0;
rlm@1 550
rlm@1 551 switch (address & 0x6000)
rlm@1 552 {
rlm@1 553 case 0x0000:
rlm@1 554 break;
rlm@1 555 case 0x2000: // ROM bank select
rlm@1 556 value = value & 0x7f;
rlm@1 557 if (value == 0)
rlm@1 558 value = 1;
rlm@1 559
rlm@1 560 if (value == gbDataMBC7.mapperROMBank)
rlm@1 561 break;
rlm@1 562
rlm@1 563 tmpAddress = (value << 14);
rlm@1 564
rlm@1 565 tmpAddress &= gbRomSizeMask;
rlm@1 566 gbDataMBC7.mapperROMBank = value;
rlm@1 567 gbMemoryMap[0x04] = &gbRom[tmpAddress];
rlm@1 568 gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
rlm@1 569 gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
rlm@1 570 gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
rlm@1 571 break;
rlm@1 572 case 0x4000: // RAM bank select/enable
rlm@1 573 if (value < 8)
rlm@1 574 {
rlm@1 575 tmpAddress = (value&3) << 13;
rlm@1 576 tmpAddress &= gbRamSizeMask;
rlm@1 577 gbMemoryMap[0x0a] = &gbMemory[0xa000];
rlm@1 578 gbMemoryMap[0x0b] = &gbMemory[0xb000];
rlm@1 579
rlm@1 580 gbDataMBC7.mapperRAMBank = value;
rlm@1 581 gbDataMBC7.mapperRAMAddress = tmpAddress;
rlm@1 582 gbDataMBC7.mapperRAMEnable = 0;
rlm@1 583 }
rlm@1 584 else
rlm@1 585 {
rlm@1 586 gbDataMBC7.mapperRAMEnable = 0;
rlm@1 587 }
rlm@1 588 break;
rlm@1 589 }
rlm@1 590 }
rlm@1 591
rlm@1 592 // MBC7 read RAM
rlm@1 593 u8 mapperMBC7ReadRAM(u16 address)
rlm@1 594 {
rlm@1 595 switch (address & 0xa0f0)
rlm@1 596 {
rlm@1 597 case 0xa000:
rlm@1 598 case 0xa010:
rlm@1 599 case 0xa060:
rlm@1 600 case 0xa070:
rlm@1 601 return 0;
rlm@1 602 case 0xa020:
rlm@1 603 // sensor X low byte
rlm@1 604 return systemGetSensorX() & 255;
rlm@1 605 case 0xa030:
rlm@1 606 // sensor X high byte
rlm@1 607 return systemGetSensorX() >> 8;
rlm@1 608 case 0xa040:
rlm@1 609 // sensor Y low byte
rlm@1 610 return systemGetSensorY() & 255;
rlm@1 611 case 0xa050:
rlm@1 612 // sensor Y high byte
rlm@1 613 return systemGetSensorY() >> 8;
rlm@1 614 case 0xa080:
rlm@1 615 return gbDataMBC7.value;
rlm@1 616 }
rlm@1 617 return 0xff;
rlm@1 618 }
rlm@1 619
rlm@1 620 // MBC7 RAM write
rlm@1 621 void mapperMBC7RAM(u16 address, u8 value)
rlm@1 622 {
rlm@1 623 if (address == 0xa080)
rlm@1 624 {
rlm@1 625 // special processing needed
rlm@1 626 int oldCs = gbDataMBC7.cs, oldSk = gbDataMBC7.sk;
rlm@1 627
rlm@1 628 gbDataMBC7.cs = value>>7;
rlm@1 629 gbDataMBC7.sk = (value>>6)&1;
rlm@1 630
rlm@1 631 if (!oldCs && gbDataMBC7.cs)
rlm@1 632 {
rlm@1 633 if (gbDataMBC7.state == 5)
rlm@1 634 {
rlm@1 635 if (gbDataMBC7.writeEnable)
rlm@1 636 {
rlm@1 637 gbWriteMemoryQuick(0xa000+gbDataMBC7.address*2, gbDataMBC7.buffer>>8);
rlm@1 638 gbWriteMemoryQuick(0xa000+gbDataMBC7.address*2+1, gbDataMBC7.buffer&0xff);
rlm@1 639 systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED;
rlm@1 640 }
rlm@1 641 gbDataMBC7.state = 0;
rlm@1 642 gbDataMBC7.value = 1;
rlm@1 643 }
rlm@1 644 else
rlm@1 645 {
rlm@1 646 gbDataMBC7.idle = true;
rlm@1 647 gbDataMBC7.state = 0;
rlm@1 648 }
rlm@1 649 }
rlm@1 650
rlm@1 651 if (!oldSk && gbDataMBC7.sk)
rlm@1 652 {
rlm@1 653 if (gbDataMBC7.idle)
rlm@1 654 {
rlm@1 655 if (value & 0x02)
rlm@1 656 {
rlm@1 657 gbDataMBC7.idle = false;
rlm@1 658 gbDataMBC7.count = 0;
rlm@1 659 gbDataMBC7.state = 1;
rlm@1 660 }
rlm@1 661 }
rlm@1 662 else
rlm@1 663 {
rlm@1 664 switch (gbDataMBC7.state)
rlm@1 665 {
rlm@1 666 case 1:
rlm@1 667 // receiving command
rlm@1 668 gbDataMBC7.buffer <<= 1;
rlm@1 669 gbDataMBC7.buffer |= (value & 0x02) ? 1 : 0;
rlm@1 670 gbDataMBC7.count++;
rlm@1 671 if (gbDataMBC7.count == 2)
rlm@1 672 {
rlm@1 673 // finished receiving command
rlm@1 674 gbDataMBC7.state = 2;
rlm@1 675 gbDataMBC7.count = 0;
rlm@1 676 gbDataMBC7.code = gbDataMBC7.buffer & 3;
rlm@1 677 }
rlm@1 678 break;
rlm@1 679 case 2:
rlm@1 680 // receive address
rlm@1 681 gbDataMBC7.buffer <<= 1;
rlm@1 682 gbDataMBC7.buffer |= (value&0x02) ? 1 : 0;
rlm@1 683 gbDataMBC7.count++;
rlm@1 684 if (gbDataMBC7.count == 8)
rlm@1 685 {
rlm@1 686 // finish receiving
rlm@1 687 gbDataMBC7.state = 3;
rlm@1 688 gbDataMBC7.count = 0;
rlm@1 689 gbDataMBC7.address = gbDataMBC7.buffer&0xff;
rlm@1 690 if (gbDataMBC7.code == 0)
rlm@1 691 {
rlm@1 692 if ((gbDataMBC7.address>>6) == 0)
rlm@1 693 {
rlm@1 694 gbDataMBC7.writeEnable = 0;
rlm@1 695 gbDataMBC7.state = 0;
rlm@1 696 }
rlm@1 697 else if ((gbDataMBC7.address>>6) == 3)
rlm@1 698 {
rlm@1 699 gbDataMBC7.writeEnable = 1;
rlm@1 700 gbDataMBC7.state = 0;
rlm@1 701 }
rlm@1 702 }
rlm@1 703 }
rlm@1 704 break;
rlm@1 705 case 3:
rlm@1 706 gbDataMBC7.buffer <<= 1;
rlm@1 707 gbDataMBC7.buffer |= (value&0x02) ? 1 : 0;
rlm@1 708 gbDataMBC7.count++;
rlm@1 709
rlm@1 710 switch (gbDataMBC7.code)
rlm@1 711 {
rlm@1 712 case 0:
rlm@1 713 if (gbDataMBC7.count == 16)
rlm@1 714 {
rlm@1 715 if ((gbDataMBC7.address>>6) == 0)
rlm@1 716 {
rlm@1 717 gbDataMBC7.writeEnable = 0;
rlm@1 718 gbDataMBC7.state = 0;
rlm@1 719 }
rlm@1 720 else if ((gbDataMBC7.address>>6) == 1)
rlm@1 721 {
rlm@1 722 if (gbDataMBC7.writeEnable)
rlm@1 723 {
rlm@1 724 for (int i = 0; i < 256; i++)
rlm@1 725 {
rlm@1 726 gbWriteMemoryQuick(0xa000+i*2, gbDataMBC7.buffer >> 8);
rlm@1 727 gbWriteMemoryQuick(0xa000+i*2+1, gbDataMBC7.buffer & 0xff);
rlm@1 728 systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED;
rlm@1 729 }
rlm@1 730 }
rlm@1 731 gbDataMBC7.state = 5;
rlm@1 732 }
rlm@1 733 else if ((gbDataMBC7.address>>6) == 2)
rlm@1 734 {
rlm@1 735 if (gbDataMBC7.writeEnable)
rlm@1 736 {
rlm@1 737 for (int i = 0; i < 256; i++)
rlm@1 738 WRITE16LE((u16 *)&gbMemory[0xa000+i*2], 0xffff);
rlm@1 739 systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED;
rlm@1 740 }
rlm@1 741 gbDataMBC7.state = 5;
rlm@1 742 }
rlm@1 743 else if ((gbDataMBC7.address>>6) == 3)
rlm@1 744 {
rlm@1 745 gbDataMBC7.writeEnable = 1;
rlm@1 746 gbDataMBC7.state = 0;
rlm@1 747 }
rlm@1 748 gbDataMBC7.count = 0;
rlm@1 749 }
rlm@1 750 break;
rlm@1 751 case 1:
rlm@1 752 if (gbDataMBC7.count == 16)
rlm@1 753 {
rlm@1 754 gbDataMBC7.count = 0;
rlm@1 755 gbDataMBC7.state = 5;
rlm@1 756 gbDataMBC7.value = 0;
rlm@1 757 }
rlm@1 758 break;
rlm@1 759 case 2:
rlm@1 760 if (gbDataMBC7.count == 1)
rlm@1 761 {
rlm@1 762 gbDataMBC7.state = 4;
rlm@1 763 gbDataMBC7.count = 0;
rlm@1 764 gbDataMBC7.buffer = (gbReadMemoryQuick(0xa000+gbDataMBC7.address*2)<<8)|
rlm@1 765 (gbReadMemoryQuick(0xa000+gbDataMBC7.address*2+1));
rlm@1 766 }
rlm@1 767 break;
rlm@1 768 case 3:
rlm@1 769 if (gbDataMBC7.count == 16)
rlm@1 770 {
rlm@1 771 gbDataMBC7.count = 0;
rlm@1 772 gbDataMBC7.state = 5;
rlm@1 773 gbDataMBC7.value = 0;
rlm@1 774 gbDataMBC7.buffer = 0xffff;
rlm@1 775 }
rlm@1 776 break;
rlm@1 777 }
rlm@1 778 break;
rlm@1 779 }
rlm@1 780 }
rlm@1 781 }
rlm@1 782
rlm@1 783 if (oldSk && !gbDataMBC7.sk)
rlm@1 784 {
rlm@1 785 if (gbDataMBC7.state == 4)
rlm@1 786 {
rlm@1 787 gbDataMBC7.value = (gbDataMBC7.buffer & 0x8000) ? 1 : 0;
rlm@1 788 gbDataMBC7.buffer <<= 1;
rlm@1 789 gbDataMBC7.count++;
rlm@1 790 if (gbDataMBC7.count == 16)
rlm@1 791 {
rlm@1 792 gbDataMBC7.count = 0;
rlm@1 793 gbDataMBC7.state = 0;
rlm@1 794 }
rlm@1 795 }
rlm@1 796 }
rlm@1 797 }
rlm@1 798 }
rlm@1 799
rlm@1 800 void memoryUpdateMapMBC7()
rlm@1 801 {
rlm@1 802 int tmpAddress = (gbDataMBC5.mapperROMBank << 14);
rlm@1 803
rlm@1 804 tmpAddress &= gbRomSizeMask;
rlm@1 805 gbMemoryMap[0x04] = &gbRom[tmpAddress];
rlm@1 806 gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
rlm@1 807 gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
rlm@1 808 gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
rlm@1 809 }
rlm@1 810
rlm@1 811 mapperHuC1 gbDataHuC1 = {
rlm@1 812 0, // RAM enable
rlm@1 813 1, // ROM bank
rlm@1 814 0, // RAM bank
rlm@1 815 0, // memory model
rlm@1 816 0, // ROM high address
rlm@1 817 0 // RAM address
rlm@1 818 };
rlm@1 819
rlm@1 820 // HuC1 ROM write registers
rlm@1 821 void mapperHuC1ROM(u16 address, u8 value)
rlm@1 822 {
rlm@1 823 int tmpAddress = 0;
rlm@1 824
rlm@1 825 switch (address & 0x6000)
rlm@1 826 {
rlm@1 827 case 0x0000: // RAM enable register
rlm@1 828 gbDataHuC1.mapperRAMEnable = ((value & 0x0a) == 0x0a ? 1 : 0);
rlm@1 829 break;
rlm@1 830 case 0x2000: // ROM bank select
rlm@1 831 value = value & 0x3f;
rlm@1 832 if (value == 0)
rlm@1 833 value = 1;
rlm@1 834 if (value == gbDataHuC1.mapperROMBank)
rlm@1 835 break;
rlm@1 836
rlm@1 837 tmpAddress = value << 14;
rlm@1 838
rlm@1 839 tmpAddress &= gbRomSizeMask;
rlm@1 840 gbDataHuC1.mapperROMBank = value;
rlm@1 841 gbMemoryMap[0x04] = &gbRom[tmpAddress];
rlm@1 842 gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
rlm@1 843 gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
rlm@1 844 gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
rlm@1 845 break;
rlm@1 846 case 0x4000: // RAM bank select
rlm@1 847 if (gbDataHuC1.mapperMemoryModel == 1)
rlm@1 848 {
rlm@1 849 // 4/32 model, RAM bank switching provided
rlm@1 850 value = value & 0x03;
rlm@1 851 if (value == gbDataHuC1.mapperRAMBank)
rlm@1 852 break;
rlm@1 853 tmpAddress = value << 13;
rlm@1 854 tmpAddress &= gbRamSizeMask;
rlm@1 855 gbMemoryMap[0x0a] = &gbRam[tmpAddress];
rlm@1 856 gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000];
rlm@1 857 gbDataHuC1.mapperRAMBank = value;
rlm@1 858 gbDataHuC1.mapperRAMAddress = tmpAddress;
rlm@1 859 }
rlm@1 860 else
rlm@1 861 {
rlm@1 862 // 16/8, set the high address
rlm@1 863 gbDataHuC1.mapperROMHighAddress = value & 0x03;
rlm@1 864 tmpAddress = gbDataHuC1.mapperROMBank << 14;
rlm@1 865 tmpAddress |= (gbDataHuC1.mapperROMHighAddress) << 19;
rlm@1 866 tmpAddress &= gbRomSizeMask;
rlm@1 867 gbMemoryMap[0x04] = &gbRom[tmpAddress];
rlm@1 868 gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
rlm@1 869 gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
rlm@1 870 gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
rlm@1 871 }
rlm@1 872 break;
rlm@1 873 case 0x6000: // memory model select
rlm@1 874 gbDataHuC1.mapperMemoryModel = value & 1;
rlm@1 875 break;
rlm@1 876 }
rlm@1 877 }
rlm@1 878
rlm@1 879 // HuC1 RAM write
rlm@1 880 void mapperHuC1RAM(u16 address, u8 value)
rlm@1 881 {
rlm@1 882 if (gbDataHuC1.mapperRAMEnable)
rlm@1 883 {
rlm@1 884 if (gbRamSize)
rlm@1 885 {
rlm@1 886 gbWriteMemoryQuick(address, value);
rlm@1 887 systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED;
rlm@1 888 }
rlm@1 889 }
rlm@1 890 }
rlm@1 891
rlm@1 892 void memoryUpdateMapHuC1()
rlm@1 893 {
rlm@1 894 int tmpAddress = gbDataHuC1.mapperROMBank << 14;
rlm@1 895
rlm@1 896 tmpAddress &= gbRomSizeMask;
rlm@1 897
rlm@1 898 gbMemoryMap[0x04] = &gbRom[tmpAddress];
rlm@1 899 gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
rlm@1 900 gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
rlm@1 901 gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
rlm@1 902
rlm@1 903 if (gbRamSize)
rlm@1 904 {
rlm@1 905 tmpAddress = gbDataHuC1.mapperRAMBank << 13;
rlm@1 906 tmpAddress &= gbRamSizeMask;
rlm@1 907 gbMemoryMap[0x0a] = &gbRam[tmpAddress];
rlm@1 908 gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000];
rlm@1 909 }
rlm@1 910 }
rlm@1 911
rlm@1 912 mapperHuC3 gbDataHuC3 = {
rlm@1 913 0, // RAM enable
rlm@1 914 1, // ROM bank
rlm@1 915 0, // RAM bank
rlm@1 916 0, // RAM address
rlm@1 917 0, // RAM flag
rlm@1 918 0 // RAM read value
rlm@1 919 };
rlm@1 920
rlm@1 921 // HuC3 ROM write registers
rlm@1 922 void mapperHuC3ROM(u16 address, u8 value)
rlm@1 923 {
rlm@1 924 int tmpAddress = 0;
rlm@1 925
rlm@1 926 switch (address & 0x6000)
rlm@1 927 {
rlm@1 928 case 0x0000: // RAM enable register
rlm@1 929 gbDataHuC3.mapperRAMEnable = (value == 0x0a ? 1 : 0);
rlm@1 930 gbDataHuC3.mapperRAMFlag = value;
rlm@1 931 if (gbDataHuC3.mapperRAMFlag != 0x0a)
rlm@1 932 gbDataHuC3.mapperRAMBank = -1;
rlm@1 933 break;
rlm@1 934 case 0x2000: // ROM bank select
rlm@1 935 value = value & 0x7f;
rlm@1 936 if (value == 0)
rlm@1 937 value = 1;
rlm@1 938 if (value == gbDataHuC3.mapperROMBank)
rlm@1 939 break;
rlm@1 940
rlm@1 941 tmpAddress = value << 14;
rlm@1 942
rlm@1 943 tmpAddress &= gbRomSizeMask;
rlm@1 944 gbDataHuC3.mapperROMBank = value;
rlm@1 945 gbMemoryMap[0x04] = &gbRom[tmpAddress];
rlm@1 946 gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
rlm@1 947 gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
rlm@1 948 gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
rlm@1 949 break;
rlm@1 950 case 0x4000: // RAM bank select
rlm@1 951 value = value & 0x03;
rlm@1 952 if (value == gbDataHuC3.mapperRAMBank)
rlm@1 953 break;
rlm@1 954 tmpAddress = value << 13;
rlm@1 955 tmpAddress &= gbRamSizeMask;
rlm@1 956 gbMemoryMap[0x0a] = &gbRam[tmpAddress];
rlm@1 957 gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000];
rlm@1 958 gbDataHuC3.mapperRAMBank = value;
rlm@1 959 gbDataHuC3.mapperRAMAddress = tmpAddress;
rlm@1 960 break;
rlm@1 961 case 0x6000: // nothing to do!
rlm@1 962 break;
rlm@1 963 }
rlm@1 964 }
rlm@1 965
rlm@1 966 // HuC3 read RAM
rlm@1 967 u8 mapperHuC3ReadRAM(u16 address)
rlm@1 968 {
rlm@1 969 if (gbDataHuC3.mapperRAMFlag > 0x0b &&
rlm@1 970 gbDataHuC3.mapperRAMFlag < 0x0e)
rlm@1 971 {
rlm@1 972 if (gbDataHuC3.mapperRAMFlag != 0x0c)
rlm@1 973 return 1;
rlm@1 974 return gbDataHuC3.mapperRAMValue;
rlm@1 975 }
rlm@1 976 else
rlm@1 977 return gbReadMemoryQuick(address);
rlm@1 978 }
rlm@1 979
rlm@1 980 // HuC3 RAM write
rlm@1 981 void mapperHuC3RAM(u16 address, u8 value)
rlm@1 982 {
rlm@1 983 int32 *p;
rlm@1 984
rlm@1 985 if (gbDataHuC3.mapperRAMFlag < 0x0b ||
rlm@1 986 gbDataHuC3.mapperRAMFlag > 0x0e)
rlm@1 987 {
rlm@1 988 if (gbDataHuC3.mapperRAMEnable)
rlm@1 989 {
rlm@1 990 if (gbRamSize)
rlm@1 991 {
rlm@1 992 gbWriteMemoryQuick(address, value);
rlm@1 993 systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED;
rlm@1 994 }
rlm@1 995 }
rlm@1 996 }
rlm@1 997 else
rlm@1 998 {
rlm@1 999 if (gbDataHuC3.mapperRAMFlag == 0x0b)
rlm@1 1000 {
rlm@1 1001 if (value == 0x62)
rlm@1 1002 {
rlm@1 1003 gbDataHuC3.mapperRAMValue = 1;
rlm@1 1004 }
rlm@1 1005 else
rlm@1 1006 {
rlm@1 1007 switch (value & 0xf0)
rlm@1 1008 {
rlm@1 1009 case 0x10:
rlm@1 1010 p = &gbDataHuC3.mapperRegister2;
rlm@1 1011 gbDataHuC3.mapperRAMValue = *(p+gbDataHuC3.mapperRegister1++);
rlm@1 1012 if (gbDataHuC3.mapperRegister1 > 6)
rlm@1 1013 gbDataHuC3.mapperRegister1 = 0;
rlm@1 1014 break;
rlm@1 1015 case 0x30:
rlm@1 1016 p = &gbDataHuC3.mapperRegister2;
rlm@1 1017 *(p+gbDataHuC3.mapperRegister1++) = value & 0x0f;
rlm@1 1018 if (gbDataHuC3.mapperRegister1 > 6)
rlm@1 1019 gbDataHuC3.mapperRegister1 = 0;
rlm@1 1020 gbDataHuC3.mapperAddress =
rlm@1 1021 (gbDataHuC3.mapperRegister6 << 24) |
rlm@1 1022 (gbDataHuC3.mapperRegister5 << 16) |
rlm@1 1023 (gbDataHuC3.mapperRegister4 << 8) |
rlm@1 1024 (gbDataHuC3.mapperRegister3 << 4) |
rlm@1 1025 (gbDataHuC3.mapperRegister2);
rlm@1 1026 break;
rlm@1 1027 case 0x40:
rlm@1 1028 gbDataHuC3.mapperRegister1 = (gbDataHuC3.mapperRegister1 & 0xf0) |
rlm@1 1029 (value & 0x0f);
rlm@1 1030 gbDataHuC3.mapperRegister2 = (gbDataHuC3.mapperAddress & 0x0f);
rlm@1 1031 gbDataHuC3.mapperRegister3 = ((gbDataHuC3.mapperAddress>>4)&0x0f);
rlm@1 1032 gbDataHuC3.mapperRegister4 = ((gbDataHuC3.mapperAddress>>8)&0x0f);
rlm@1 1033 gbDataHuC3.mapperRegister5 = ((gbDataHuC3.mapperAddress>>16)&0x0f);
rlm@1 1034 gbDataHuC3.mapperRegister6 = ((gbDataHuC3.mapperAddress>>24)&0x0f);
rlm@1 1035 gbDataHuC3.mapperRegister7 = 0;
rlm@1 1036 gbDataHuC3.mapperRegister8 = 0;
rlm@1 1037 gbDataHuC3.mapperRAMValue = 0;
rlm@1 1038 break;
rlm@1 1039 case 0x50:
rlm@1 1040 gbDataHuC3.mapperRegister1 = (gbDataHuC3.mapperRegister1 & 0x0f) |
rlm@1 1041 ((value << 4)&0x0f);
rlm@1 1042 break;
rlm@1 1043 default:
rlm@1 1044 gbDataHuC3.mapperRAMValue = 1;
rlm@1 1045 break;
rlm@1 1046 }
rlm@1 1047 }
rlm@1 1048 }
rlm@1 1049 }
rlm@1 1050 }
rlm@1 1051
rlm@1 1052 void memoryUpdateMapHuC3()
rlm@1 1053 {
rlm@1 1054 int tmpAddress = gbDataHuC3.mapperROMBank << 14;
rlm@1 1055
rlm@1 1056 tmpAddress &= gbRomSizeMask;
rlm@1 1057 gbMemoryMap[0x04] = &gbRom[tmpAddress];
rlm@1 1058 gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
rlm@1 1059 gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
rlm@1 1060 gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
rlm@1 1061
rlm@1 1062 if (gbRamSize)
rlm@1 1063 {
rlm@1 1064 tmpAddress = gbDataHuC3.mapperRAMBank << 13;
rlm@1 1065 tmpAddress &= gbRamSizeMask;
rlm@1 1066 gbMemoryMap[0x0a] = &gbRam[tmpAddress];
rlm@1 1067 gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000];
rlm@1 1068 }
rlm@1 1069 }
rlm@1 1070