SameBoy | Accurate GB/GBC emulator |
| download: https://git.y1.nz/archives/sameboy.tar.gz | |
| README | Files | Log | Refs | LICENSE |
Core/memory.c
1 #include <stdio.h>
2 #include <stdbool.h>
3 #include <string.h>
4 #include "gb.h"
5
6 typedef uint8_t read_function_t(GB_gameboy_t *gb, uint16_t addr);
7 typedef void write_function_t(GB_gameboy_t *gb, uint16_t addr, uint8_t value);
8
9 typedef enum {
10 GB_BUS_MAIN, /* In DMG: Cart and RAM. In CGB: Cart only */
11 GB_BUS_RAM, /* In CGB only. */
12 GB_BUS_VRAM,
13 } bus_t;
14
15 static bus_t bus_for_addr(GB_gameboy_t *gb, uint16_t addr)
16 {
17 if (addr < 0x8000) {
18 return GB_BUS_MAIN;
19 }
20 if (addr < 0xA000) {
21 return GB_BUS_VRAM;
22 }
23 if (addr < 0xC000) {
24 return GB_BUS_MAIN;
25 }
26 return GB_is_cgb(gb)? GB_BUS_RAM : GB_BUS_MAIN;
27 }
28
29 static uint16_t bitwise_glitch(uint16_t a, uint16_t b, uint16_t c)
30 {
31 return ((a ^ c) & (b ^ c)) ^ c;
32 }
33
34 static uint16_t bitwise_glitch_read(uint16_t a, uint16_t b, uint16_t c)
35 {
36 return b | (a & c);
37 }
38
39 static uint16_t bitwise_glitch_read_secondary(uint16_t a, uint16_t b, uint16_t c, uint16_t d)
40 {
41 return (b & (a | c | d)) | (a & c & d);
42 }
43
44 /*
45 Used on the MGB in some scenarios
46 static uint16_t bitwise_glitch_mgb(uint16_t a, uint16_t b, uint16_t c, uint16_t d, uint16_t e, bool variant)
47 {
48 return (c & (e | d | b | (variant? 0 : a))) | (b & d & (a | e));
49 }
50 */
51
52 static uint16_t bitwise_glitch_tertiary_read_1(uint16_t a, uint16_t b, uint16_t c, uint16_t d, uint16_t e)
53 {
54 return c | (a & b & d & e);
55 }
56
57 static uint16_t bitwise_glitch_tertiary_read_2(uint16_t a, uint16_t b, uint16_t c, uint16_t d, uint16_t e)
58 {
59 return (c & (a | b | d | e)) | (a & b & d & e);
60 }
61
62 static uint16_t bitwise_glitch_tertiary_read_3(uint16_t a, uint16_t b, uint16_t c, uint16_t d, uint16_t e)
63 {
64 return (c & (a | b | d | e)) | (b & d & e);
65 }
66
67 static uint16_t bitwise_glitch_quaternary_read_dmg(uint16_t a, uint16_t b, uint16_t c, uint16_t d,
68 uint16_t e, uint16_t f, uint16_t g, uint16_t h)
69 {
70 /* On my DMG, some cases are non-deterministic, while on some other DMGs they yield constant zeros.
71 The non deterministic cases are affected by (on the row 40 case) 34, 36, 3e and 28, and potentially
72 others. For my own sanity I'm going to emulate the DMGs that output zeros. */
73 (void)a;
74 return (e & (h | g | (~d & f) | c | b)) | (c & g & h);
75 }
76
77 /*
78
79 // Oh my.
80 static uint16_t bitwise_glitch_quaternary_read_mgb(uint16_t a, uint16_t b, uint16_t c, uint16_t d,
81 uint16_t e, uint16_t f, uint16_t g, uint16_t h)
82 {
83 return (e & (h | g | c | (a & b))) | ((c & h) & (g & (~f | b | a | ~d) | (a & b & f)));
84 }
85 */
86
87 static uint16_t bitwise_glitch_quaternary_read_sgb2(uint16_t a, uint16_t b, uint16_t c, uint16_t d,
88 uint16_t e, uint16_t f, uint16_t g, uint16_t h)
89 {
90 return (e & (h | g | c | (a & b))) | ((c & g & h) & (b | a | ~f));
91 }
92
93 void GB_trigger_oam_bug(GB_gameboy_t *gb, uint16_t address)
94 {
95 if (GB_is_cgb(gb)) return;
96
97 if (address >= 0xFE00 && address < 0xFF00) {
98 GB_display_sync(gb);
99 if (gb->accessed_oam_row != 0xFF && gb->accessed_oam_row >= 8) {
100 uint16_t *base = (uint16_t *)(gb->oam + gb->accessed_oam_row);
101 base[0] = bitwise_glitch(base[0],
102 base[-4],
103 base[-2]);
104 for (unsigned i = 2; i < 8; i++) {
105 gb->oam[gb->accessed_oam_row + i] = gb->oam[gb->accessed_oam_row - 8 + i];
106 }
107 }
108 }
109 }
110
111 static void oam_bug_secondary_read_corruption(GB_gameboy_t *gb)
112 {
113 if (gb->accessed_oam_row < 0x98) {
114 uint16_t *base = (uint16_t *)(gb->oam + gb->accessed_oam_row);
115 base[-4] = bitwise_glitch_read_secondary(base[-8],
116 base[-4],
117 base[0],
118 base[-2]);
119 for (unsigned i = 0; i < 8; i++) {
120 gb->oam[gb->accessed_oam_row - 0x10 + i] = gb->oam[gb->accessed_oam_row - 0x08 + i];
121 }
122 }
123 }
124
125 /*
126 static void oam_bug_tertiary_read_corruption_mgb(GB_gameboy_t *gb)
127 {
128 if (gb->accessed_oam_row < 0x98) {
129 uint16_t *base = (uint16_t *)(gb->oam + gb->accessed_oam_row);
130 uint16_t temp = bitwise_glitch_mgb(
131 base[0],
132 base[-2],
133 base[-4],
134 base[-8],
135 base[-16],
136 true);
137
138 base[-4] = bitwise_glitch_mgb(
139 base[0],
140 base[-2],
141 base[-4],
142 base[-8],
143 base[-16],
144 false);
145 for (unsigned i = 0; i < 8; i++) {
146 gb->oam[gb->accessed_oam_row - 0x10 + i] = gb->oam[gb->accessed_oam_row - 0x20 + i] = gb->oam[gb->accessed_oam_row - 0x08 + i];
147 }
148
149 base[-8] = temp;
150 base[-16] = temp;
151 }
152 }
153 */
154
155 static void oam_bug_quaternary_read_corruption(GB_gameboy_t *gb, typeof(bitwise_glitch_quaternary_read_dmg) *bitwise_op)
156 {
157 if (gb->accessed_oam_row < 0x98) {
158 uint16_t *base = (uint16_t *)(gb->oam + gb->accessed_oam_row);
159
160 base[-4] = bitwise_op(*(uint16_t *)gb->oam,
161 base[0],
162 base[-2],
163 base[-3],
164 base[-4],
165 base[-7],
166 base[-8],
167 base[-16]);
168 for (unsigned i = 0; i < 8; i++) {
169 gb->oam[gb->accessed_oam_row - 0x10 + i] = gb->oam[gb->accessed_oam_row - 0x20 + i] = gb->oam[gb->accessed_oam_row - 0x08 + i];
170 }
171 }
172 }
173
174 static void oam_bug_tertiary_read_corruption(GB_gameboy_t *gb, typeof(bitwise_glitch_tertiary_read_1) *bitwise_op)
175 {
176 if (gb->accessed_oam_row < 0x98) {
177 uint16_t *base = (uint16_t *)(gb->oam + gb->accessed_oam_row);
178
179 /* On some instances, the corruption row is copied to the first row for some accessed row. On my DMG it happens
180 for row 80, and on my MGB it happens on row 60. Some instances only copy odd or even bytes. Additionally,
181 for some instances on accessed rows that do not affect the first row, the last two bytes of the preceeding
182 row are also corrupted in a non-deterministic probability. */
183
184 base[-4] = bitwise_op(
185 base[0],
186 base[-2],
187 base[-4],
188 base[-8],
189 base[-16]);
190 for (unsigned i = 0; i < 8; i++) {
191 gb->oam[gb->accessed_oam_row - 0x10 + i] = gb->oam[gb->accessed_oam_row - 0x20 + i] = gb->oam[gb->accessed_oam_row - 0x08 + i];
192 }
193 }
194 }
195
196 void GB_trigger_oam_bug_read(GB_gameboy_t *gb, uint16_t address)
197 {
198 if (GB_is_cgb(gb)) return;
199
200 if (address >= 0xFE00 && address < 0xFF00) {
201 if (gb->accessed_oam_row != 0xFF && gb->accessed_oam_row >= 8) {
202 if ((gb->accessed_oam_row & 0x18) == 0x10) {
203 oam_bug_secondary_read_corruption(gb);
204 }
205 else if ((gb->accessed_oam_row & 0x18) == 0x00) {
206 /* Everything in this specific case is *extremely* revision and instance specific. */
207 if (gb->model == GB_MODEL_MGB) {
208 /* TODO: This is rather simplified, research further */
209 oam_bug_tertiary_read_corruption(gb, bitwise_glitch_tertiary_read_3);
210 }
211 else if (gb->accessed_oam_row == 0x40) {
212 oam_bug_quaternary_read_corruption(gb,
213 ((gb->model & ~GB_MODEL_NO_SFC_BIT) == GB_MODEL_SGB2)?
214 bitwise_glitch_quaternary_read_sgb2:
215 bitwise_glitch_quaternary_read_dmg);
216 }
217 else if ((gb->model & ~GB_MODEL_NO_SFC_BIT) != GB_MODEL_SGB2) {
218 if (gb->accessed_oam_row == 0x20) {
219 oam_bug_tertiary_read_corruption(gb, bitwise_glitch_tertiary_read_2);
220 }
221 else if (gb->accessed_oam_row == 0x60) {
222 oam_bug_tertiary_read_corruption(gb, bitwise_glitch_tertiary_read_3);
223 }
224 else {
225 oam_bug_tertiary_read_corruption(gb, bitwise_glitch_tertiary_read_1);
226 }
227 }
228 else {
229 oam_bug_tertiary_read_corruption(gb, bitwise_glitch_tertiary_read_2);
230 }
231 }
232 else {
233 uint16_t *base = (uint16_t *)(gb->oam + gb->accessed_oam_row);
234 base[-4] =
235 base[0] = bitwise_glitch_read(base[0],
236 base[-4],
237 base[-2]);
238 }
239 for (unsigned i = 0; i < 8; i++) {
240 gb->oam[gb->accessed_oam_row + i] = gb->oam[gb->accessed_oam_row - 8 + i];
241 }
242 if (gb->accessed_oam_row == 0x80) {
243 memcpy(gb->oam, gb->oam + gb->accessed_oam_row, 8);
244 }
245 else if (gb->model == GB_MODEL_MGB && gb->accessed_oam_row == 0x40) {
246 memcpy(gb->oam, gb->oam + gb->accessed_oam_row, 8);
247 }
248 }
249 }
250 }
251
252
253 static bool is_addr_in_dma_use(GB_gameboy_t *gb, uint16_t addr)
254 {
255 if (!GB_is_dma_active(gb) || addr >= 0xFE00 || gb->hdma_in_progress) return false;
256 if (gb->dma_current_dest == 0xFF || gb->dma_current_dest == 0x0) return false; // Warm up
257 if (addr >= 0xFE00) return false;
258 if (gb->dma_current_src == addr) return false; // Shortcut for DMA access flow
259 if (gb->dma_current_src >= 0xE000 && (gb->dma_current_src & ~0x2000) == addr) return false;
260 if (GB_is_cgb(gb)) {
261 if (addr >= 0xC000) {
262 return bus_for_addr(gb, gb->dma_current_src) != GB_BUS_VRAM;
263 }
264 if (gb->dma_current_src >= 0xE000) {
265 return bus_for_addr(gb, addr) != GB_BUS_VRAM;
266 }
267 }
268 return bus_for_addr(gb, addr) == bus_for_addr(gb, gb->dma_current_src);
269 }
270
271 static uint8_t read_rom(GB_gameboy_t *gb, uint16_t addr)
272 {
273 if (addr < 0x100 && !gb->boot_rom_finished) {
274 return gb->boot_rom[addr];
275 }
276
277 if (addr >= 0x200 && addr < 0x900 && GB_is_cgb(gb) && !gb->boot_rom_finished) {
278 return gb->boot_rom[addr];
279 }
280
281 if (!gb->rom_size) {
282 return 0xFF;
283 }
284 unsigned effective_address = (addr & 0x3FFF) + gb->mbc_rom0_bank * 0x4000;
285 return gb->rom[effective_address & (gb->rom_size - 1)];
286 }
287
288 static uint8_t read_mbc_rom(GB_gameboy_t *gb, uint16_t addr)
289 {
290 unsigned effective_address = (addr & 0x3FFF) + gb->mbc_rom_bank * 0x4000;
291 return gb->rom[effective_address & (gb->rom_size - 1)];
292 }
293
294 static uint8_t read_vram(GB_gameboy_t *gb, uint16_t addr)
295 {
296 if (likely(!GB_is_dma_active(gb))) {
297 /* Prevent syncing from a DMA read. Batching doesn't happen during DMA anyway. */
298 GB_display_sync(gb);
299 }
300 else {
301 if (unlikely((gb->dma_current_dest & 0xE000) == 0x8000)) {
302 // TODO: verify conflict behavior
303 return gb->cpu_vram_bus = gb->vram[(addr & 0x1FFF) + (gb->cgb_vram_bank? 0x2000 : 0)];
304 }
305 }
306
307 if (unlikely(gb->vram_read_blocked && !gb->in_dma_read)) {
308 return 0xFF;
309 }
310 if (unlikely(gb->display_state == 22)) {
311 if (!GB_is_cgb(gb)) {
312 if (addr & 0x1000 && !(gb->last_tile_data_address & 0x1000)) {
313 addr &= ~0x1000; // TODO: verify
314 }
315 }
316 else if (!gb->cgb_double_speed) {
317 if (addr & 0x1000) {
318 if (gb->model <= GB_MODEL_CGB_C && !(gb->last_tile_data_address & 0x1000)) {
319 return 0;
320 }
321 addr = gb->last_tile_index_address;
322 }
323 else if (gb->last_tile_data_address & 0x1000) {
324 if (gb->model >= GB_MODEL_CGB_E) {
325 uint8_t ret = gb->cpu_vram_bus;
326 gb->cpu_vram_bus = gb->vram[(addr & 0x1FFF) + (gb->cgb_vram_bank? 0x2000 : 0)];
327 return ret;
328 }
329 return gb->cpu_vram_bus;
330 }
331 else {
332 addr = gb->last_tile_data_address;
333 }
334 }
335 }
336 return gb->cpu_vram_bus = gb->vram[(addr & 0x1FFF) + (gb->cgb_vram_bank? 0x2000 : 0)];
337 }
338
339 static uint8_t read_mbc7_ram(GB_gameboy_t *gb, uint16_t addr)
340 {
341 if (!gb->mbc_ram_enable || !gb->mbc7.secondary_ram_enable) return 0xFF;
342 if (addr >= 0xB000) return 0xFF;
343 switch ((addr >> 4) & 0xF) {
344 case 2: return gb->mbc7.x_latch;
345 case 3: return gb->mbc7.x_latch >> 8;
346 case 4: return gb->mbc7.y_latch;
347 case 5: return gb->mbc7.y_latch >> 8;
348 case 6: return 0;
349 case 8: return gb->mbc7.eeprom_do | (gb->mbc7.eeprom_di << 1) |
350 (gb->mbc7.eeprom_clk << 6) | (gb->mbc7.eeprom_cs << 7);
351 }
352 return 0xFF;
353 }
354
355 static uint8_t read_mbc_ram(GB_gameboy_t *gb, uint16_t addr)
356 {
357 if (gb->cartridge_type->mbc_type == GB_MBC7) {
358 return read_mbc7_ram(gb, addr);
359 }
360
361 if (gb->cartridge_type->mbc_type == GB_HUC3) {
362 switch (gb->huc3.mode) {
363 case 0xC: // RTC read
364 if (gb->huc3.access_flags == 0x2) {
365 return 1;
366 }
367 return gb->huc3.read;
368 case 0xD: // RTC status
369 return 1;
370 case 0xE: // IR mode
371 return gb->effective_ir_input; // TODO: What are the other bits?
372 default:
373 GB_log(gb, "Unsupported HuC-3 mode %x read: %04x\n", gb->huc3.mode, addr);
374 return 1; // TODO: What happens in this case?
375 case 0: // TODO: R/O RAM? (or is it disabled?)
376 case 0xA: // RAM
377 break;
378 }
379 }
380
381 if (gb->cartridge_type->mbc_type == GB_TPP1) {
382 switch (gb->tpp1.mode) {
383 case 0:
384 switch (addr & 3) {
385 case 0: return gb->tpp1.rom_bank;
386 case 1: return gb->tpp1.rom_bank >> 8;
387 case 2: return gb->tpp1.ram_bank;
388 case 3: return gb->rumble_strength | gb->tpp1_mr4;
389 nodefault;
390 }
391 case 2:
392 case 3:
393 break; // Read RAM
394 case 5:
395 return gb->rtc_latched.data[(addr & 3) ^ 3];
396 default:
397 gb->returned_open_bus = true;
398 return gb->data_bus;
399 }
400 }
401 else if ((!gb->mbc_ram_enable) &&
402 gb->cartridge_type->mbc_type != GB_CAMERA &&
403 gb->cartridge_type->mbc_type != GB_HUC1 &&
404 gb->cartridge_type->mbc_type != GB_HUC3) {
405 gb->returned_open_bus = true;
406 return gb->data_bus;
407 }
408
409 if (gb->cartridge_type->mbc_type == GB_HUC1 && gb->huc1.ir_mode) {
410 return 0xC0 | gb->effective_ir_input;
411 }
412
413 if (gb->cartridge_type->has_rtc && gb->cartridge_type->mbc_type != GB_HUC3 &&
414 gb->mbc3.rtc_mapped) {
415 /* RTC read */
416 if (gb->mbc_ram_bank <= 4) {
417 gb->rtc_latched.seconds &= 0x3F;
418 gb->rtc_latched.minutes &= 0x3F;
419 gb->rtc_latched.hours &= 0x1F;
420 gb->rtc_latched.high &= 0xC1;
421 return gb->rtc_latched.data[gb->mbc_ram_bank];
422 }
423 gb->returned_open_bus = true;
424 return gb->data_bus;
425 }
426
427 if (gb->camera_registers_mapped) {
428 return GB_camera_read_register(gb, addr);
429 }
430
431 if (!gb->mbc_ram || !gb->mbc_ram_size) {
432 gb->returned_open_bus = true;
433 return gb->data_bus;
434 }
435
436 if (gb->cartridge_type->mbc_type == GB_CAMERA) {
437 /* Forbid reading RAM while the camera is busy. */
438 if (gb->camera_registers[GB_CAMERA_SHOOT_AND_1D_FLAGS] & 1) {
439 return 0;
440 }
441
442 if (gb->mbc_ram_bank == 0 && addr >= 0xA100 && addr < 0xAF00) {
443 return GB_camera_read_image(gb, addr - 0xA100);
444 }
445 }
446
447 uint8_t effective_bank = gb->mbc_ram_bank;
448 if (gb->cartridge_type->mbc_type == GB_MBC3 && !gb->is_mbc30) {
449 if (gb->cartridge_type->has_rtc) {
450 if (effective_bank > 3) return 0xFF;
451 }
452 effective_bank &= 0x3;
453 }
454 uint8_t ret = gb->mbc_ram[((addr & 0x1FFF) + effective_bank * 0x2000) & (gb->mbc_ram_size - 1)];
455 if (gb->cartridge_type->mbc_type == GB_MBC2) {
456 ret |= 0xF0;
457 }
458 return ret;
459 }
460
461 static uint8_t read_ram(GB_gameboy_t *gb, uint16_t addr)
462 {
463 return gb->ram[addr & 0x0FFF];
464 }
465
466 static uint8_t read_banked_ram(GB_gameboy_t *gb, uint16_t addr)
467 {
468 return gb->ram[(addr & 0x0FFF) + gb->cgb_ram_bank * 0x1000];
469 }
470
471 static inline void sync_ppu_if_needed(GB_gameboy_t *gb, uint8_t register_accessed)
472 {
473 switch (register_accessed) {
474 case GB_IO_IF:
475 case GB_IO_LCDC:
476 case GB_IO_STAT:
477 case GB_IO_SCY:
478 case GB_IO_SCX:
479 case GB_IO_LY:
480 case GB_IO_LYC:
481 case GB_IO_DMA:
482 case GB_IO_BGP:
483 case GB_IO_OBP0:
484 case GB_IO_OBP1:
485 case GB_IO_WY:
486 case GB_IO_WX:
487 case GB_IO_HDMA1:
488 case GB_IO_HDMA2:
489 case GB_IO_HDMA3:
490 case GB_IO_HDMA4:
491 case GB_IO_HDMA5:
492 case GB_IO_BGPI:
493 case GB_IO_BGPD:
494 case GB_IO_OBPI:
495 case GB_IO_OBPD:
496 case GB_IO_OPRI:
497 GB_display_sync(gb);
498 break;
499 }
500 }
501
502 internal uint8_t GB_read_oam(GB_gameboy_t *gb, uint8_t addr)
503 {
504 if (addr < 0xA0) {
505 return gb->oam[addr];
506 }
507
508 switch (gb->model) {
509 case GB_MODEL_CGB_E:
510 case GB_MODEL_AGB_A:
511 case GB_MODEL_GBP_A:
512 return (addr & 0xF0) | (addr >> 4);
513
514 case GB_MODEL_CGB_D:
515 if (addr >= 0xC0) {
516 addr |= 0xF0;
517 }
518 return gb->extra_oam[addr - 0xA0];
519
520 case GB_MODEL_CGB_C:
521 case GB_MODEL_CGB_B:
522 case GB_MODEL_CGB_A:
523 case GB_MODEL_CGB_0:
524 addr &= ~0x18;
525 return gb->extra_oam[addr - 0xA0];
526
527 case GB_MODEL_DMG_B:
528 case GB_MODEL_MGB:
529 case GB_MODEL_SGB_NTSC:
530 case GB_MODEL_SGB_PAL:
531 case GB_MODEL_SGB_NTSC_NO_SFC:
532 case GB_MODEL_SGB_PAL_NO_SFC:
533 case GB_MODEL_SGB2:
534 case GB_MODEL_SGB2_NO_SFC:
535 return 0;
536 }
537 unreachable();
538 }
539
540 static uint8_t read_high_memory(GB_gameboy_t *gb, uint16_t addr)
541 {
542 if (addr < 0xFE00) {
543 return read_banked_ram(gb, addr);
544 }
545
546 if (addr < 0xFF00) {
547 GB_display_sync(gb);
548 if (gb->oam_write_blocked && !GB_is_cgb(gb)) {
549 if (!gb->disable_oam_corruption) {
550 GB_trigger_oam_bug_read(gb, addr);
551 }
552 return 0xFF;
553 }
554
555 if (GB_is_dma_active(gb) && (gb->dma_current_dest != 0 || gb->dma_restarting)) {
556 /* Todo: Does reading from OAM during DMA causes the OAM bug? */
557 return 0xFF;
558 }
559
560 if (gb->oam_read_blocked) {
561 if (!GB_is_cgb(gb) && !gb->disable_oam_corruption) {
562 if (addr < 0xFEA0) {
563 uint16_t *oam = (uint16_t *)gb->oam;
564 if (gb->accessed_oam_row == 0) {
565 oam[(addr & 0xF8) >> 1] =
566 oam[0] = bitwise_glitch_read(oam[0],
567 oam[(addr & 0xF8) >> 1],
568 oam[(addr & 0xFF) >> 1]);
569
570 for (unsigned i = 2; i < 8; i++) {
571 gb->oam[i] = gb->oam[(addr & 0xF8) + i];
572 }
573 }
574 else if (gb->accessed_oam_row == 0xA0) {
575 uint8_t target = (addr & 7) | 0x98;
576 uint16_t a = oam[0x9C >> 1],
577 b = oam[target >> 1],
578 c = oam[(addr & 0xF8) >> 1];
579 switch (addr & 7) {
580 case 0:
581 case 1:
582 /* Probably instance specific */
583 if ((gb->model & GB_MODEL_FAMILY_MASK) == GB_MODEL_DMG_FAMILY) {
584 oam[target >> 1] = (a & b) | (a & c) | (b & c);
585 }
586 else {
587 oam[target >> 1] = bitwise_glitch_read(a, b, c);
588 }
589 break;
590 case 2:
591 case 3: {
592 /* Probably instance specific */
593 c = oam[(addr & 0xFE) >> 1];
594
595 // MGB only: oam[target >> 1] = bitwise_glitch_read(a, b, c);
596 oam[target >> 1] = (a & b) | (a & c) | (b & c);
597 break;
598 }
599 case 4:
600 case 5:
601 break; // No additional corruption
602 case 6:
603 case 7:
604 oam[target >> 1] = bitwise_glitch_read(a, b, c);
605 break;
606
607 nodefault;
608 }
609
610 for (unsigned i = 0; i < 8; i++) {
611 gb->oam[(addr & 0xF8) + i] = gb->oam[0x98 + i];
612 }
613 }
614 }
615 }
616 return 0xFF;
617 }
618
619 return GB_read_oam(gb, addr);
620 }
621
622 if (addr < 0xFF80) {
623 sync_ppu_if_needed(gb, addr);
624 switch (addr & 0xFF) {
625 case GB_IO_IF:
626 return gb->io_registers[GB_IO_IF] | 0xE0;
627 case GB_IO_TAC:
628 return gb->io_registers[GB_IO_TAC] | 0xF8;
629 case GB_IO_STAT:
630 return gb->io_registers[GB_IO_STAT] | 0x80;
631 case GB_IO_OPRI:
632 if (!GB_is_cgb(gb)) {
633 return 0xFF;
634 }
635 return gb->io_registers[GB_IO_OPRI] | 0xFE;
636
637 case GB_IO_PCM12:
638 if (!GB_is_cgb(gb)) return 0xFF;
639 GB_apu_run(gb, true);
640 return ((gb->apu.is_active[GB_SQUARE_2] ? (gb->apu.samples[GB_SQUARE_2] << 4) : 0) |
641 (gb->apu.is_active[GB_SQUARE_1] ? (gb->apu.samples[GB_SQUARE_1]) : 0)) & (gb->model <= GB_MODEL_CGB_C? gb->apu.pcm_mask[0] : 0xFF);
642 case GB_IO_PCM34:
643 if (!GB_is_cgb(gb)) return 0xFF;
644 GB_apu_run(gb, true);
645 return ((gb->apu.is_active[GB_NOISE] ? (gb->apu.samples[GB_NOISE] << 4) : 0) |
646 (gb->apu.is_active[GB_WAVE] ? (gb->apu.samples[GB_WAVE]) : 0)) & (gb->model <= GB_MODEL_CGB_C? gb->apu.pcm_mask[1] : 0xFF);
647 case GB_IO_JOYP:
648 gb->joyp_accessed = true;
649 GB_timing_sync(gb);
650 if (unlikely(gb->joyp_switching_delay)) {
651 return (gb->io_registers[addr & 0xFF] & ~0x30) | (gb->joyp_switch_value & 0x30);
652 }
653 return gb->io_registers[addr & 0xFF];
654 case GB_IO_TMA:
655 case GB_IO_LCDC:
656 case GB_IO_SCY:
657 case GB_IO_SCX:
658 case GB_IO_LY:
659 case GB_IO_LYC:
660 case GB_IO_BGP:
661 case GB_IO_OBP0:
662 case GB_IO_OBP1:
663 case GB_IO_WY:
664 case GB_IO_WX:
665 case GB_IO_SC:
666 case GB_IO_SB:
667 case GB_IO_DMA:
668 return gb->io_registers[addr & 0xFF];
669 case GB_IO_TIMA:
670 if (gb->tima_reload_state == GB_TIMA_RELOADING) {
671 return 0;
672 }
673 return gb->io_registers[GB_IO_TIMA];
674 case GB_IO_DIV:
675 return gb->div_counter >> 8;
676 case GB_IO_HDMA5:
677 if (!gb->cgb_mode) return 0xFF;
678 return ((gb->hdma_on || gb->hdma_on_hblank)? 0 : 0x80) | ((gb->hdma_steps_left - 1) & 0x7F);
679 case GB_IO_SVBK:
680 if (!gb->cgb_mode) {
681 return 0xFF;
682 }
683
684 return gb->io_registers[GB_IO_SVBK];
685 case GB_IO_VBK:
686 if (!GB_is_cgb(gb)) {
687 return 0xFF;
688 }
689 return gb->cgb_vram_bank | ~0x1;
690
691 /* Todo: It seems that a CGB in DMG mode can access BGPI and OBPI, but not BGPD and OBPD? */
692 case GB_IO_BGPI:
693 case GB_IO_OBPI:
694 if (!GB_is_cgb(gb)) {
695 return 0xFF;
696 }
697 return gb->io_registers[addr & 0xFF] | 0x40;
698
699 case GB_IO_BGPD:
700 case GB_IO_OBPD:
701 {
702 if (!gb->cgb_mode && gb->boot_rom_finished) {
703 return 0xFF;
704 }
705 if (gb->cgb_palettes_blocked) {
706 return 0xFF;
707 }
708 uint8_t index_reg = (addr & 0xFF) - 1;
709 return ((addr & 0xFF) == GB_IO_BGPD?
710 gb->background_palettes_data :
711 gb->object_palettes_data)[gb->io_registers[index_reg] & 0x3F];
712 }
713
714 case GB_IO_KEY1:
715 if (!gb->cgb_mode) {
716 return 0xFF;
717 }
718 return (gb->io_registers[GB_IO_KEY1] & 0x7F) | (gb->cgb_double_speed? 0xFE : 0x7E);
719 case GB_IO_BANK:
720 return 0xFE | gb->boot_rom_finished;
721 case GB_IO_RP: {
722 if (!gb->cgb_mode) return 0xFF;
723 /* You will read your own IR LED if it's on. */
724 uint8_t ret = (gb->io_registers[GB_IO_RP] & 0xC1) | 0x2E;
725 if (gb->model != GB_MODEL_CGB_E) {
726 ret |= 0x10;
727 }
728 if (((gb->io_registers[GB_IO_RP] & 0xC0) == 0xC0 && gb->effective_ir_input) && gb->model <= GB_MODEL_CGB_E) {
729 ret &= ~2;
730 }
731 return ret;
732 }
733 case GB_IO_PSWX:
734 case GB_IO_PSWY:
735 return GB_is_cgb(gb)? gb->io_registers[addr & 0xFF] : 0xFF;
736 case GB_IO_PSW:
737 return gb->cgb_mode? gb->io_registers[addr & 0xFF] : 0xFF;
738 case GB_IO_PGB:
739 return GB_is_cgb(gb)? gb->io_registers[addr & 0xFF] | 0x8F : 0xFF;
740 default:
741 if ((addr & 0xFF) >= GB_IO_NR10 && (addr & 0xFF) <= GB_IO_WAV_END) {
742 return GB_apu_read(gb, addr & 0xFF);
743 }
744 return 0xFF;
745 }
746 unreachable();
747 }
748
749 if (addr == 0xFFFF) {
750 /* Interrupt Mask */
751 return gb->interrupt_enable;
752 }
753
754 /* HRAM */
755 return gb->hram[addr - 0xFF80];
756 }
757
758 static read_function_t *const read_map[] =
759 {
760 read_rom, read_rom, read_rom, read_rom, /* 0XXX, 1XXX, 2XXX, 3XXX */
761 read_mbc_rom, read_mbc_rom, read_mbc_rom, read_mbc_rom, /* 4XXX, 5XXX, 6XXX, 7XXX */
762 read_vram, read_vram, /* 8XXX, 9XXX */
763 read_mbc_ram, read_mbc_ram, /* AXXX, BXXX */
764 read_ram, read_banked_ram, /* CXXX, DXXX */
765 read_ram, read_high_memory, /* EXXX FXXX */
766 };
767
768 void GB_set_read_memory_callback(GB_gameboy_t *gb, GB_read_memory_callback_t callback)
769 {
770 if (!callback) {
771 GB_ASSERT_NOT_RUNNING_OTHER_THREAD(gb)
772 }
773 gb->read_memory_callback = callback;
774 }
775
776 uint8_t GB_read_memory(GB_gameboy_t *gb, uint16_t addr)
777 {
778 GB_ASSERT_NOT_RUNNING_OTHER_THREAD(gb)
779
780 #ifndef GB_DISABLE_DEBUGGER
781 if (unlikely(gb->n_watchpoints)) {
782 GB_debugger_test_read_watchpoint(gb, addr);
783 }
784 #endif
785 if (unlikely(is_addr_in_dma_use(gb, addr))) {
786 if (GB_is_cgb(gb) && bus_for_addr(gb, addr) == GB_BUS_MAIN && gb->dma_current_src >= 0xE000) {
787 /* This is cart specific! Everdrive 7X on a CGB-A or 0 behaves differently. */
788 return 0xFF;
789 }
790
791 if (GB_is_cgb(gb) && bus_for_addr(gb, gb->dma_current_src) != GB_BUS_RAM && addr >= 0xC000) {
792 // TODO: this should probably affect the DMA dest as well
793 addr = ((gb->dma_current_src - 1) & 0x1000) | (addr & 0xFFF) | 0xC000;
794 }
795 else if (GB_is_cgb(gb) && gb->dma_current_src >= 0xE000 && addr >= 0xC000) {
796 // TODO: this should probably affect the DMA dest as well
797 addr = ((gb->dma_current_src - 1) & 0x1000) | (addr & 0xFFF) | 0xC000;
798 }
799 else {
800 addr = (gb->dma_current_src - 1);
801 }
802 }
803 uint8_t data = read_map[addr >> 12](gb, addr);
804 GB_apply_cheat(gb, addr, &data);
805 if (unlikely(gb->read_memory_callback)) {
806 data = gb->read_memory_callback(gb, addr, data);
807 }
808
809 /* TODO: this is very naïve due to my lack of a cart that properly handles open-bus scnenarios,
810 but should be good enough */
811 if (bus_for_addr(gb, addr) == GB_BUS_MAIN && addr < 0xFF00) {
812 if (unlikely(gb->returned_open_bus)) {
813 gb->returned_open_bus = false;
814 }
815 else {
816 gb->data_bus = data;
817 gb->data_bus_decay_countdown = gb->data_bus_decay;
818 }
819 }
820 return data;
821 }
822
823 uint8_t GB_safe_read_memory(GB_gameboy_t *gb, uint16_t addr)
824 {
825 GB_ASSERT_NOT_RUNNING_OTHER_THREAD(gb)
826
827 if (unlikely(addr == 0xFF00 + GB_IO_JOYP)) {
828 return gb->io_registers[GB_IO_JOYP];
829 }
830 gb->disable_oam_corruption = true;
831 uint8_t data = read_map[addr >> 12](gb, addr);
832 gb->disable_oam_corruption = false;
833 GB_apply_cheat(gb, addr, &data);
834 if (unlikely(gb->read_memory_callback)) {
835 data = gb->read_memory_callback(gb, addr, data);
836 }
837 return data;
838 }
839
840 static void write_mbc(GB_gameboy_t *gb, uint16_t addr, uint8_t value)
841 {
842 switch (gb->cartridge_type->mbc_type) {
843 case GB_NO_MBC: return;
844 case GB_MBC1:
845 switch (addr & 0xF000) {
846 case 0x0000: case 0x1000: gb->mbc_ram_enable = (value & 0xF) == 0xA; break;
847 case 0x2000: case 0x3000: gb->mbc1.bank_low = value; break;
848 case 0x4000: case 0x5000: gb->mbc1.bank_high = value; break;
849 case 0x6000: case 0x7000: gb->mbc1.mode = value; break;
850 }
851 break;
852 case GB_MBC2:
853 switch (addr & 0x4100) {
854 case 0x0000: gb->mbc_ram_enable = (value & 0xF) == 0xA; break;
855 case 0x0100: gb->mbc2.rom_bank = value; break;
856 }
857 break;
858 case GB_MBC3:
859 switch (addr & 0xF000) {
860 case 0x0000: case 0x1000: gb->mbc_ram_enable = (value & 0xF) == 0xA; break;
861 case 0x2000: case 0x3000: gb->mbc3.rom_bank = value; break;
862 case 0x4000: case 0x5000:
863 gb->mbc3.ram_bank = value;
864 gb->mbc3.rtc_mapped = value & 8;
865 break;
866 case 0x6000: case 0x7000:
867 memcpy(&gb->rtc_latched, &gb->rtc_real, sizeof(gb->rtc_real));
868 gb->battery_dirty = true;
869 break;
870 }
871 break;
872 case GB_MBC5:
873 switch (addr & 0xF000) {
874 case 0x0000: case 0x1000: gb->mbc_ram_enable = value == 0x0A; break;
875 case 0x2000: gb->mbc5.rom_bank_low = value; break;
876 case 0x3000: gb->mbc5.rom_bank_high = value; break;
877 case 0x4000: case 0x5000:
878 if (gb->cartridge_type->has_rumble) {
879 if (!!(value & 8) != !!gb->rumble_strength) {
880 gb->rumble_strength = gb->rumble_strength? 0 : 3;
881 }
882 value &= 7;
883 }
884 gb->mbc5.ram_bank = value;
885 break;
886 }
887 break;
888 case GB_CAMERA:
889 switch (addr & 0xF000) {
890 case 0x0000: case 0x1000: gb->mbc_ram_enable = (value & 0xF) == 0xA; break;
891 case 0x2000: case 0x3000: gb->mbc5.rom_bank_low = value; break;
892 case 0x4000: case 0x5000:
893 gb->mbc5.ram_bank = value;
894 gb->camera_registers_mapped = (value & 0x10);
895 break;
896 }
897 break;
898 case GB_MBC7:
899 switch (addr & 0xF000) {
900 case 0x0000: case 0x1000: gb->mbc_ram_enable = value == 0x0A; break;
901 case 0x2000: case 0x3000: gb->mbc7.rom_bank = value; break;
902 case 0x4000: case 0x5000: gb->mbc7.secondary_ram_enable = value == 0x40; break;
903 }
904 break;
905 case GB_MMM01:
906 switch (addr & 0xF000) {
907 case 0x0000: case 0x1000:
908 gb->mbc_ram_enable = (value & 0xF) == 0xA;
909 if (!gb->mmm01.locked) {
910 gb->mmm01.ram_bank_mask = value >> 4;
911 gb->mmm01.locked = value & 0x40;
912 }
913 break;
914 case 0x2000: case 0x3000:
915 if (!gb->mmm01.locked) {
916 gb->mmm01.rom_bank_mid = value >> 5;
917 }
918 gb->mmm01.rom_bank_low &= (gb->mmm01.rom_bank_mask << 1);
919 gb->mmm01.rom_bank_low |= ~(gb->mmm01.rom_bank_mask << 1) & value;
920 break;
921 case 0x4000: case 0x5000:
922 gb->mmm01.ram_bank_low = value | ~gb->mmm01.ram_bank_mask;
923 if (!gb->mmm01.locked) {
924 gb->mmm01.ram_bank_high = value >> 2;
925 gb->mmm01.rom_bank_high = value >> 4;
926 gb->mmm01.mbc1_mode_disable = value & 0x40;
927 }
928 break;
929 case 0x6000: case 0x7000:
930 if (!gb->mmm01.mbc1_mode_disable) {
931 gb->mmm01.mbc1_mode = (value & 1);
932 }
933 if (!gb->mmm01.locked) {
934 gb->mmm01.rom_bank_mask = value >> 2;
935 gb->mmm01.multiplex_mode = value & 0x40;
936 }
937 break;
938 }
939 break;
940 case GB_HUC1:
941 switch (addr & 0xF000) {
942 case 0x0000: case 0x1000: gb->huc1.ir_mode = (value & 0xF) == 0xE; break;
943 case 0x2000: case 0x3000: gb->huc1.bank_low = value; break;
944 case 0x4000: case 0x5000: gb->huc1.bank_high = value; break;
945 }
946 break;
947 case GB_HUC3:
948 switch (addr & 0xF000) {
949 case 0x0000: case 0x1000:
950 gb->huc3.mode = value;
951 gb->mbc_ram_enable = gb->huc3.mode == 0xA;
952 break;
953 case 0x2000: case 0x3000: gb->huc3.rom_bank = value; break;
954 case 0x4000: case 0x5000: gb->huc3.ram_bank = value; break;
955 }
956 break;
957 case GB_TPP1:
958 switch (addr & 3) {
959 case 0:
960 gb->tpp1.rom_bank &= 0xFF00;
961 gb->tpp1.rom_bank |= value;
962 break;
963 case 1:
964 gb->tpp1.rom_bank &= 0xFF;
965 gb->tpp1.rom_bank |= value << 8;
966 break;
967 case 2:
968 gb->tpp1.ram_bank = value;
969 break;
970 case 3:
971 switch (value) {
972 case 0:
973 case 2:
974 case 3:
975 case 5:
976 gb->tpp1.mode = value;
977 break;
978 case 0x10:
979 memcpy(&gb->rtc_latched, &gb->rtc_real, sizeof(gb->rtc_real));
980 gb->battery_dirty = true;
981 break;
982 case 0x11: {
983 memcpy(&gb->rtc_real, &gb->rtc_latched, sizeof(gb->rtc_real));
984 gb->battery_dirty = true;
985 break;
986 }
987 case 0x14:
988 gb->tpp1_mr4 &= ~0x8;
989 break;
990 case 0x18:
991 gb->tpp1_mr4 &= ~0x4;
992 break;
993 case 0x19:
994 gb->tpp1_mr4 |= 0x4;
995 break;
996
997 case 0x20:
998 case 0x21:
999 case 0x22:
1000 case 0x23:
1001 gb->rumble_strength = value & 3;
1002 break;
1003 }
1004 }
1005 break;
1006 nodefault;
1007 }
1008 GB_update_mbc_mappings(gb);
1009 }
1010
1011 static void write_vram(GB_gameboy_t *gb, uint16_t addr, uint8_t value)
1012 {
1013 GB_display_sync(gb);
1014 if (unlikely(gb->vram_write_blocked)) {
1015 //GB_log(gb, "Wrote %02x to %04x (VRAM) during mode 3\n", value, addr);
1016 return;
1017 }
1018 gb->vram[(addr & 0x1FFF) + (gb->cgb_vram_bank? 0x2000 : 0)] = value;
1019 }
1020
1021 static bool huc3_write(GB_gameboy_t *gb, uint8_t value)
1022 {
1023 switch (gb->huc3.mode) {
1024 case 0xB: // RTC Write
1025 switch (value >> 4) {
1026 case 1:
1027 if (gb->huc3.access_index < 3) {
1028 gb->huc3.read = (gb->huc3.minutes >> (gb->huc3.access_index * 4)) & 0xF;
1029 }
1030 else if (gb->huc3.access_index < 7) {
1031 gb->huc3.read = (gb->huc3.days >> ((gb->huc3.access_index - 3) * 4)) & 0xF;
1032 }
1033 else {
1034 // GB_log(gb, "Attempting to read from unsupported HuC-3 register: %03x\n", gb->huc3.access_index);
1035 }
1036 gb->huc3.access_index++;
1037 break;
1038 case 2:
1039 case 3:
1040 if (gb->huc3.access_index < 3) {
1041 gb->huc3.minutes &= ~(0xF << (gb->huc3.access_index * 4));
1042 gb->huc3.minutes |= ((value & 0xF) << (gb->huc3.access_index * 4));
1043 }
1044 else if (gb->huc3.access_index < 7) {
1045 gb->huc3.days &= ~(0xF << ((gb->huc3.access_index - 3) * 4));
1046 gb->huc3.days |= ((value & 0xF) << ((gb->huc3.access_index - 3) * 4));
1047 }
1048 else if (gb->huc3.access_index >= 0x58 && gb->huc3.access_index <= 0x5A) {
1049 gb->huc3.alarm_minutes &= ~(0xF << ((gb->huc3.access_index - 0x58) * 4));
1050 gb->huc3.alarm_minutes |= ((value & 0xF) << ((gb->huc3.access_index - 0x58) * 4));
1051 gb->battery_dirty = true;
1052 }
1053 else if (gb->huc3.access_index >= 0x5B && gb->huc3.access_index <= 0x5E) {
1054 gb->huc3.alarm_days &= ~(0xF << ((gb->huc3.access_index - 0x5B) * 4));
1055 gb->huc3.alarm_days |= ((value & 0xF) << ((gb->huc3.access_index - 0x5B) * 4));
1056 gb->battery_dirty = true;
1057 }
1058 else if (gb->huc3.access_index == 0x5F) {
1059 gb->huc3.alarm_enabled = value & 1;
1060 gb->battery_dirty = true;
1061 }
1062 else {
1063 // GB_log(gb, "Attempting to write %x to unsupported HuC-3 register: %03x\n", value & 0xF, gb->huc3.access_index);
1064 }
1065 if ((value >> 4) == 3) {
1066 gb->huc3.access_index++;
1067 }
1068 break;
1069 case 4:
1070 gb->huc3.access_index &= 0xF0;
1071 gb->huc3.access_index |= value & 0xF;
1072 break;
1073 case 5:
1074 gb->huc3.access_index &= 0x0F;
1075 gb->huc3.access_index |= (value & 0xF) << 4;
1076 break;
1077 case 6:
1078 gb->huc3.access_flags = (value & 0xF);
1079 break;
1080
1081 default:
1082 break;
1083 }
1084
1085 return true;
1086 case 0xD: // RTC status
1087 // Not sure what writes here mean, they're always 0xFE
1088 return true;
1089 case 0xE: { // IR mode
1090 if (gb->cart_ir != (value & 1)) {
1091 gb->cart_ir = value & 1;
1092 if (gb->infrared_callback) {
1093 gb->infrared_callback(gb, value & 1);
1094 }
1095 }
1096 return true;
1097 }
1098 case 0xC:
1099 return true;
1100 default:
1101 return false;
1102 case 0: // Disabled
1103 case 0xA: // RAM
1104 return false;
1105 }
1106 }
1107
1108 static void write_mbc7_ram(GB_gameboy_t *gb, uint16_t addr, uint8_t value)
1109 {
1110 if (!gb->mbc_ram_enable || !gb->mbc7.secondary_ram_enable) return;
1111 if (addr >= 0xB000) return;
1112 switch ((addr >> 4) & 0xF) {
1113 case 0: {
1114 if (value == 0x55) {
1115 gb->mbc7.latch_ready = true;
1116 gb->mbc7.x_latch = gb->mbc7.y_latch = 0x8000;
1117 }
1118 break;
1119 }
1120 case 1: {
1121 if (value == 0xAA) {
1122 gb->mbc7.latch_ready = false;
1123 gb->mbc7.x_latch = 0x81D0 + 0x70 * gb->accelerometer_x;
1124 gb->mbc7.y_latch = 0x81D0 + 0x70 * gb->accelerometer_y;
1125 }
1126 break;
1127 }
1128 case 8: {
1129 gb->mbc7.eeprom_cs = value & 0x80;
1130 gb->mbc7.eeprom_di = value & 2;
1131 if (gb->mbc7.eeprom_cs) {
1132 if (!gb->mbc7.eeprom_clk && (value & 0x40)) { // Clocked
1133 gb->mbc7.eeprom_do = gb->mbc7.read_bits >> 15;
1134 gb->mbc7.read_bits <<= 1;
1135 gb->mbc7.read_bits |= 1;
1136 if (gb->mbc7.argument_bits_left == 0) {
1137 /* Not transferring extra bits for a command*/
1138 gb->mbc7.eeprom_command <<= 1;
1139 gb->mbc7.eeprom_command |= gb->mbc7.eeprom_di;
1140 if (gb->mbc7.eeprom_command & 0x400) {
1141 // Got full command
1142 switch ((gb->mbc7.eeprom_command >> 6) & 0xF) {
1143 case 0x8:
1144 case 0x9:
1145 case 0xA:
1146 case 0xB:
1147 // READ
1148 gb->mbc7.read_bits = LE16(((uint16_t *)gb->mbc_ram)[gb->mbc7.eeprom_command & 0x7F]);
1149 gb->mbc7.eeprom_command = 0;
1150 break;
1151 case 0x3: // EWEN (Eeprom Write ENable)
1152 gb->mbc7.eeprom_write_enabled = true;
1153 gb->mbc7.eeprom_command = 0;
1154 break;
1155 case 0x0: // EWDS (Eeprom Write DiSable)
1156 gb->mbc7.eeprom_write_enabled = false;
1157 gb->mbc7.eeprom_command = 0;
1158 break;
1159 case 0x4:
1160 case 0x5:
1161 case 0x6:
1162 case 0x7:
1163 // WRITE
1164 if (gb->mbc7.eeprom_write_enabled) {
1165 ((uint16_t *)gb->mbc_ram)[gb->mbc7.eeprom_command & 0x7F] = 0;
1166 gb->battery_dirty = true;
1167 }
1168 gb->mbc7.argument_bits_left = 16;
1169 // We still need to process this command, don't erase eeprom_command
1170 break;
1171 case 0xC:
1172 case 0xD:
1173 case 0xE:
1174 case 0xF:
1175 // ERASE
1176 if (gb->mbc7.eeprom_write_enabled) {
1177 ((uint16_t *)gb->mbc_ram)[gb->mbc7.eeprom_command & 0x7F] = 0xFFFF;
1178 gb->battery_dirty = true;
1179 gb->mbc7.read_bits = 0x3FFF; // Emulate some time to settle
1180 }
1181 gb->mbc7.eeprom_command = 0;
1182 break;
1183 case 0x2:
1184 // ERAL (ERase ALl)
1185 if (gb->mbc7.eeprom_write_enabled) {
1186 memset(gb->mbc_ram, 0xFF, gb->mbc_ram_size);
1187 ((uint16_t *)gb->mbc_ram)[gb->mbc7.eeprom_command & 0x7F] = 0xFFFF;
1188 gb->battery_dirty = true;
1189 gb->mbc7.read_bits = 0xFF; // Emulate some time to settle
1190 }
1191 gb->mbc7.eeprom_command = 0;
1192 break;
1193 case 0x1:
1194 // WRAL (WRite ALl)
1195 if (gb->mbc7.eeprom_write_enabled) {
1196 memset(gb->mbc_ram, 0, gb->mbc_ram_size);
1197 gb->battery_dirty = true;
1198 }
1199 gb->mbc7.argument_bits_left = 16;
1200 // We still need to process this command, don't erase eeprom_command
1201 break;
1202 }
1203 }
1204 }
1205 else {
1206 // We're shifting in extra bits for a WRITE/WRAL command
1207 gb->mbc7.argument_bits_left--;
1208 gb->mbc7.eeprom_do = true;
1209 if (gb->mbc7.eeprom_di) {
1210 uint16_t bit = LE16(1 << gb->mbc7.argument_bits_left);
1211 if (gb->mbc7.eeprom_command & 0x100) {
1212 // WRITE
1213 ((uint16_t *)gb->mbc_ram)[gb->mbc7.eeprom_command & 0x7F] |= bit;
1214 gb->battery_dirty = true;
1215 }
1216 else {
1217 // WRAL
1218 for (unsigned i = 0; i < 0x7F; i++) {
1219 ((uint16_t *)gb->mbc_ram)[i] |= bit;
1220 gb->battery_dirty = true;
1221 }
1222 }
1223 }
1224 if (gb->mbc7.argument_bits_left == 0) { // We're done
1225 gb->mbc7.eeprom_command = 0;
1226 gb->mbc7.read_bits = (gb->mbc7.eeprom_command & 0x100)? 0xFF : 0x3FFF; // Emulate some time to settle
1227 }
1228 }
1229 }
1230 }
1231 gb->mbc7.eeprom_clk = value & 0x40;
1232 break;
1233 }
1234 }
1235 }
1236
1237 static void write_mbc_ram(GB_gameboy_t *gb, uint16_t addr, uint8_t value)
1238 {
1239 if (gb->cartridge_type->mbc_type == GB_MBC7) {
1240 write_mbc7_ram(gb, addr, value);
1241 return;
1242 }
1243
1244 if (gb->cartridge_type->mbc_type == GB_HUC3) {
1245 if (huc3_write(gb, value)) return;
1246 }
1247
1248 if (gb->camera_registers_mapped) {
1249 GB_camera_write_register(gb, addr, value);
1250 return;
1251 }
1252
1253 if (gb->cartridge_type->mbc_type == GB_TPP1) {
1254 switch (gb->tpp1.mode) {
1255 case 3:
1256 break;
1257 case 5:
1258 gb->rtc_latched.data[(addr & 3) ^ 3] = value;
1259 return;
1260 default:
1261 return;
1262 }
1263 }
1264
1265 if ((!gb->mbc_ram_enable)
1266 && gb->cartridge_type->mbc_type != GB_HUC1) return;
1267
1268 if (gb->cartridge_type->mbc_type == GB_HUC1 && gb->huc1.ir_mode) {
1269 if (gb->cart_ir != (value & 1)) {
1270 gb->cart_ir = value & 1;
1271 if (gb->infrared_callback) {
1272 gb->infrared_callback(gb, value & 1);
1273 }
1274 }
1275 return;
1276 }
1277
1278 if (gb->cartridge_type->has_rtc && gb->mbc3.rtc_mapped) {
1279 if (gb->mbc_ram_bank <= 4) {
1280 if (gb->mbc_ram_bank == 0) {
1281 gb->rtc_cycles = 0;
1282 }
1283 gb->rtc_real.data[gb->mbc_ram_bank] = value;
1284 }
1285 return;
1286 }
1287
1288 if (!gb->mbc_ram || !gb->mbc_ram_size) {
1289 return;
1290 }
1291
1292 if (gb->cartridge_type->mbc_type == GB_CAMERA && (gb->camera_registers[GB_CAMERA_SHOOT_AND_1D_FLAGS] & 1)) {
1293 /* Forbid writing to RAM while the camera is busy. */
1294 return;
1295 }
1296
1297 uint8_t effective_bank = gb->mbc_ram_bank;
1298 if (gb->cartridge_type->mbc_type == GB_MBC3 && !gb->is_mbc30) {
1299 if (gb->cartridge_type->has_rtc) {
1300 if (effective_bank > 3) return;
1301 }
1302 effective_bank &= 0x3;
1303 }
1304
1305 gb->mbc_ram[((addr & 0x1FFF) + effective_bank * 0x2000) & (gb->mbc_ram_size - 1)] = value;
1306 gb->battery_dirty = true;
1307 }
1308
1309 static void write_ram(GB_gameboy_t *gb, uint16_t addr, uint8_t value)
1310 {
1311 gb->ram[addr & 0x0FFF] = value;
1312 }
1313
1314 static void write_banked_ram(GB_gameboy_t *gb, uint16_t addr, uint8_t value)
1315 {
1316 gb->ram[(addr & 0x0FFF) + gb->cgb_ram_bank * 0x1000] = value;
1317 }
1318
1319 static void write_oam(GB_gameboy_t *gb, uint8_t addr, uint8_t value)
1320 {
1321 if (addr < 0xA0) {
1322 gb->oam[addr] = value;
1323 return;
1324 }
1325 switch (gb->model) {
1326 case GB_MODEL_CGB_D:
1327 if (addr >= 0xC0) {
1328 addr |= 0xF0;
1329 }
1330 gb->extra_oam[addr - 0xA0] = value;
1331 break;
1332 case GB_MODEL_CGB_C:
1333 case GB_MODEL_CGB_B:
1334 case GB_MODEL_CGB_A:
1335 case GB_MODEL_CGB_0:
1336 addr &= ~0x18;
1337 gb->extra_oam[addr - 0xA0] = value;
1338 break;
1339 case GB_MODEL_CGB_E:
1340 case GB_MODEL_AGB_A:
1341 case GB_MODEL_GBP_A:
1342 case GB_MODEL_DMG_B:
1343 case GB_MODEL_MGB:
1344 case GB_MODEL_SGB_NTSC:
1345 case GB_MODEL_SGB_PAL:
1346 case GB_MODEL_SGB_NTSC_NO_SFC:
1347 case GB_MODEL_SGB_PAL_NO_SFC:
1348 case GB_MODEL_SGB2:
1349 case GB_MODEL_SGB2_NO_SFC:
1350 break;
1351 }
1352 }
1353
1354 static void write_high_memory(GB_gameboy_t *gb, uint16_t addr, uint8_t value)
1355 {
1356 if (addr < 0xFE00) {
1357 GB_log(gb, "Wrote %02x to %04x (RAM Mirror)\n", value, addr);
1358 write_banked_ram(gb, addr, value);
1359 return;
1360 }
1361
1362 if (addr < 0xFF00) {
1363 GB_display_sync(gb);
1364 if (gb->oam_write_blocked) {
1365 GB_trigger_oam_bug(gb, addr);
1366 return;
1367 }
1368
1369 if (GB_is_dma_active(gb)) {
1370 /* Todo: Does writing to OAM during DMA causes the OAM bug? */
1371 return;
1372 }
1373
1374 if (GB_is_cgb(gb)) {
1375 write_oam(gb, addr, value);
1376 return;
1377 }
1378
1379 if (addr < 0xFEA0) {
1380 if (gb->accessed_oam_row == 0xA0) {
1381 for (unsigned i = 0; i < 8; i++) {
1382 if ((i & 6) != (addr & 6)) {
1383 gb->oam[(addr & 0xF8) + i] = gb->oam[0x98 + i];
1384 }
1385 else {
1386 gb->oam[(addr & 0xF8) + i] = bitwise_glitch(gb->oam[(addr & 0xF8) + i], gb->oam[0x9C], gb->oam[0x98 + i]);
1387 }
1388 }
1389 }
1390
1391 gb->oam[addr & 0xFF] = value;
1392
1393 if (gb->accessed_oam_row == 0) {
1394 gb->oam[0] = bitwise_glitch(gb->oam[0],
1395 gb->oam[(addr & 0xF8)],
1396 gb->oam[(addr & 0xFE)]);
1397 gb->oam[1] = bitwise_glitch(gb->oam[1],
1398 gb->oam[(addr & 0xF8) + 1],
1399 gb->oam[(addr & 0xFE) | 1]);
1400 for (unsigned i = 2; i < 8; i++) {
1401 gb->oam[i] = gb->oam[(addr & 0xF8) + i];
1402 }
1403 }
1404 }
1405 else if (gb->accessed_oam_row == 0) {
1406 gb->oam[addr & 0x7] = value;
1407 }
1408 return;
1409 }
1410
1411 /* Todo: Clean this code up: use a function table and move relevant code to display.c and timing.c
1412 (APU read and writes are already at apu.c) */
1413 if (addr < 0xFF80) {
1414 sync_ppu_if_needed(gb, addr);
1415
1416 /* Hardware registers */
1417 switch (addr & 0xFF) {
1418
1419 case GB_IO_WX:
1420 gb->io_registers[addr & 0xFF] = value;
1421 GB_update_wx_glitch(gb);
1422 break;
1423
1424 case GB_IO_IF:
1425 case GB_IO_SCX:
1426 case GB_IO_SCY:
1427 case GB_IO_BGP:
1428 case GB_IO_OBP0:
1429 case GB_IO_OBP1:
1430 case GB_IO_SB:
1431 case GB_IO_PSWX:
1432 case GB_IO_PSWY:
1433 case GB_IO_PSW:
1434 case GB_IO_PGB:
1435 gb->io_registers[addr & 0xFF] = value;
1436 return;
1437 case GB_IO_OPRI:
1438 if ((!gb->boot_rom_finished || (gb->io_registers[GB_IO_KEY0] & 8)) && GB_is_cgb(gb)) {
1439 gb->io_registers[addr & 0xFF] = value;
1440 gb->object_priority = (value & 1) ? GB_OBJECT_PRIORITY_X : GB_OBJECT_PRIORITY_INDEX;
1441 }
1442 else if (gb->cgb_mode) {
1443 gb->io_registers[addr & 0xFF] = value;
1444
1445 }
1446 return;
1447 case GB_IO_WY:
1448 gb->io_registers[addr & 0xFF] = value;
1449 gb->wy_check_scheduled = true;
1450 return;
1451
1452 case GB_IO_LYC:
1453 /* TODO: Probably completely wrong in double speed mode */
1454
1455 /* TODO: This hack is disgusting */
1456 if (gb->display_state == 29 && GB_is_cgb(gb)) {
1457 gb->ly_for_comparison = 153;
1458 GB_STAT_update(gb);
1459 gb->ly_for_comparison = 0;
1460 }
1461
1462 gb->io_registers[addr & 0xFF] = value;
1463
1464 /* These are the states when LY changes, let the display routine call GB_STAT_update for use
1465 so it correctly handles T-cycle accurate LYC writes */
1466 if (!GB_is_cgb(gb) || (
1467 gb->display_state != 35 &&
1468 gb->display_state != 26 &&
1469 gb->display_state != 15 &&
1470 gb->display_state != 16)) {
1471
1472 /* More hacks to make LYC write conflicts work */
1473 if (gb->display_state == 14 && GB_is_cgb(gb)) {
1474 gb->ly_for_comparison = 153;
1475 GB_STAT_update(gb);
1476 gb->ly_for_comparison = -1;
1477 }
1478 else {
1479 GB_STAT_update(gb);
1480 }
1481 }
1482 return;
1483
1484 case GB_IO_TIMA:
1485 if (gb->tima_reload_state != GB_TIMA_RELOADED) {
1486 gb->io_registers[GB_IO_TIMA] = value;
1487 }
1488 return;
1489
1490 case GB_IO_TMA:
1491 gb->io_registers[GB_IO_TMA] = value;
1492 if (gb->tima_reload_state != GB_TIMA_RUNNING) {
1493 gb->io_registers[GB_IO_TIMA] = value;
1494 }
1495 return;
1496
1497 case GB_IO_TAC:
1498 GB_emulate_timer_glitch(gb, gb->io_registers[GB_IO_TAC], value);
1499 gb->io_registers[GB_IO_TAC] = value;
1500 return;
1501
1502
1503 case GB_IO_LCDC:
1504 if ((value & GB_LCDC_ENABLE) && !(gb->io_registers[GB_IO_LCDC] & GB_LCDC_ENABLE)) {
1505 // LCD turned on
1506 if (gb->lcd_status_callback) {
1507 gb->lcd_status_callback(gb, true);
1508 }
1509 if (!gb->lcd_disabled_outside_of_vblank &&
1510 (gb->cycles_since_vblank_callback > 10 * 456)) {
1511 // Trigger a vblank here so we don't exceed LCDC_PERIOD
1512 GB_display_vblank(gb, GB_VBLANK_TYPE_ARTIFICIAL);
1513 }
1514
1515 gb->display_cycles = 0;
1516 gb->display_state = 0;
1517 gb->double_speed_alignment = 0;
1518 gb->cycles_for_line = 0;
1519 if (GB_is_sgb(gb)) {
1520 gb->frame_skip_state = GB_FRAMESKIP_FIRST_FRAME_RENDERED;
1521 }
1522 else {
1523 gb->frame_skip_state = GB_FRAMESKIP_LCD_TURNED_ON;
1524 }
1525 GB_timing_sync(gb);
1526 }
1527 else if (!(value & GB_LCDC_ENABLE) && (gb->io_registers[GB_IO_LCDC] & GB_LCDC_ENABLE)) {
1528 /* Sync after turning off LCD */
1529 if (gb->lcd_status_callback) {
1530 gb->lcd_status_callback(gb, false);
1531 }
1532 gb->double_speed_alignment = 0;
1533 if (gb->model <= GB_MODEL_CGB_E) {
1534 /* TODO: Verify this, it's a bit... odd */
1535 gb->is_odd_frame ^= true;
1536 }
1537 GB_timing_sync(gb);
1538 GB_lcd_off(gb);
1539 }
1540 /* Handle disabling objects while already fetching an object */
1541 if (!GB_is_cgb(gb) && (gb->io_registers[GB_IO_LCDC] & GB_LCDC_OBJ_EN) && !(value & GB_LCDC_OBJ_EN)) {
1542 if (gb->during_object_fetch) {
1543 gb->cycles_for_line += gb->display_cycles / 2;
1544 gb->display_cycles = 0;
1545 gb->object_fetch_aborted = true;
1546 }
1547 }
1548 gb->io_registers[GB_IO_LCDC] = value;
1549 gb->wy_check_scheduled = true;
1550 return;
1551
1552 case GB_IO_STAT:
1553 gb->io_registers[GB_IO_STAT] &= 7;
1554 gb->io_registers[GB_IO_STAT] |= value & ~7;
1555 gb->io_registers[GB_IO_STAT] |= 0x80;
1556
1557 /* Annoying edge timing case */
1558 if (gb->cgb_double_speed &&
1559 gb->display_state == 8 &&
1560 gb->oam_search_index == 0 &&
1561 gb->display_cycles == 0 &&
1562 (value & 0x20)) {
1563 gb->mode_for_interrupt = 2;
1564 GB_STAT_update(gb);
1565 gb->mode_for_interrupt = -1;
1566 }
1567 else {
1568 GB_STAT_update(gb);
1569 }
1570 return;
1571
1572 case GB_IO_DIV:
1573 gb->during_div_write = true;
1574 GB_set_internal_div_counter(gb, 0);
1575 gb->during_div_write = false;
1576 /* Reset the div state machine */
1577 gb->div_state = 0;
1578 gb->div_cycles = 0;
1579 return;
1580
1581 case GB_IO_JOYP:
1582 if (gb->joyp_write_callback) {
1583 gb->joyp_write_callback(gb, value);
1584 GB_update_joyp(gb);
1585 }
1586 else if ((gb->io_registers[GB_IO_JOYP] & 0x30) != (value & 0x30)) {
1587 if (!GB_is_cgb(gb) && !GB_is_sgb(gb)) {
1588 if (gb->joyp_switching_delay) {
1589 gb->io_registers[GB_IO_JOYP] = (gb->joyp_switch_value & 0xF0) | (gb->io_registers[GB_IO_JOYP] & 0x0F);
1590 }
1591 gb->joyp_switch_value = value;
1592 uint8_t delay = 0;
1593 switch (((gb->io_registers[GB_IO_JOYP] & 0x30) >> 4) |
1594 ((value & 0x30) >> 2)) {
1595 case 0x4: delay = 48; break;
1596 case 0x6: delay = gb->model == GB_MODEL_MGB? 56 : 48; break;
1597 case 0x8: delay = 24; break;
1598 case 0x9: delay = 24; break;
1599 case 0xC: delay = 48; break;
1600 case 0xD: delay = 24; break;
1601 case 0xE: delay = 48; break;
1602 }
1603 if (delay && gb->model == GB_MODEL_MGB) {
1604 delay -= 16;
1605 }
1606 gb->joyp_switching_delay = MAX(gb->joyp_switching_delay, delay);
1607 if (gb->joyp_switching_delay) {
1608 value &= gb->io_registers[GB_IO_JOYP];
1609 gb->joypad_is_stable = false;
1610 }
1611 }
1612 GB_sgb_write(gb, value);
1613 gb->io_registers[GB_IO_JOYP] = (value & 0xF0) | (gb->io_registers[GB_IO_JOYP] & 0x0F);
1614 GB_update_joyp(gb);
1615 }
1616 return;
1617
1618 case GB_IO_BANK:
1619 gb->boot_rom_finished |= value & 1;
1620 return;
1621
1622 case GB_IO_KEY0:
1623 if (GB_is_cgb(gb) && !gb->boot_rom_finished) {
1624 gb->cgb_mode = !(value & 0xC); /* The real "contents" of this register aren't quite known yet. */
1625 gb->io_registers[GB_IO_KEY0] = value;
1626 }
1627 return;
1628
1629 case GB_IO_DMA:
1630 gb->dma_restarting = (gb->dma_current_dest != 0xA1 && gb->dma_current_dest != 0xA0);
1631 gb->dma_cycles = 0;
1632 gb->dma_cycles_modulo = 2;
1633 gb->dma_current_dest = 0xFF;
1634 gb->dma_current_src = value << 8;
1635 gb->io_registers[GB_IO_DMA] = value;
1636 GB_STAT_update(gb);
1637 return;
1638 case GB_IO_SVBK:
1639 if (gb->cgb_mode || (GB_is_cgb(gb) && !gb->boot_rom_finished)) {
1640 gb->cgb_ram_bank = value & 0x7;
1641 if (!gb->cgb_ram_bank) {
1642 gb->cgb_ram_bank++;
1643 }
1644 gb->io_registers[GB_IO_SVBK] = value | ~0x7;
1645 }
1646 return;
1647 case GB_IO_VBK:
1648 if (!gb->cgb_mode) {
1649 return;
1650 }
1651 gb->cgb_vram_bank = value & 0x1;
1652 return;
1653
1654 case GB_IO_BGPI:
1655 case GB_IO_OBPI:
1656 if (!GB_is_cgb(gb)) {
1657 return;
1658 }
1659 gb->io_registers[addr & 0xFF] = value;
1660 return;
1661 case GB_IO_BGPD:
1662 case GB_IO_OBPD:
1663 if (!gb->cgb_mode && gb->boot_rom_finished) {
1664 /* Todo: Due to the behavior of a broken Game & Watch Gallery 2 ROM on a real CGB. A proper test ROM
1665 is required. */
1666 return;
1667 }
1668
1669 uint8_t index_reg = (addr & 0xFF) - 1;
1670 if (gb->cgb_palettes_blocked) {
1671 if (gb->io_registers[index_reg] & 0x80) {
1672 gb->io_registers[index_reg]++;
1673 gb->io_registers[index_reg] |= 0x80;
1674 }
1675 return;
1676 }
1677 ((addr & 0xFF) == GB_IO_BGPD?
1678 gb->background_palettes_data :
1679 gb->object_palettes_data)[gb->io_registers[index_reg] & 0x3F] = value;
1680 GB_palette_changed(gb, (addr & 0xFF) == GB_IO_BGPD, gb->io_registers[index_reg] & 0x3F);
1681 if (gb->io_registers[index_reg] & 0x80) {
1682 gb->io_registers[index_reg]++;
1683 gb->io_registers[index_reg] |= 0x80;
1684 }
1685 return;
1686 case GB_IO_KEY1:
1687 if (!gb->cgb_mode) {
1688 return;
1689 }
1690 gb->io_registers[GB_IO_KEY1] = value;
1691 return;
1692 case GB_IO_HDMA1:
1693 if (gb->cgb_mode) {
1694 gb->hdma_current_src &= 0xF0;
1695 gb->hdma_current_src |= value << 8;
1696 }
1697 /* Range 0xE*** like 0xF*** and can't overflow (with 0x800 bytes) to anything meaningful */
1698 if (gb->hdma_current_src >= 0xE000) {
1699 gb->hdma_current_src |= 0xF000;
1700 }
1701 return;
1702 case GB_IO_HDMA2:
1703 if (gb->cgb_mode) {
1704 gb->hdma_current_src &= 0xFF00;
1705 gb->hdma_current_src |= value & 0xF0;
1706 }
1707 return;
1708 case GB_IO_HDMA3:
1709 if (gb->cgb_mode) {
1710 gb->hdma_current_dest &= 0xF0;
1711 gb->hdma_current_dest |= value << 8;
1712 }
1713 return;
1714 case GB_IO_HDMA4:
1715 if (gb->cgb_mode) {
1716 gb->hdma_current_dest &= 0xFF00;
1717 gb->hdma_current_dest |= value & 0xF0;
1718 }
1719 return;
1720 case GB_IO_HDMA5:
1721 if (!gb->cgb_mode) return;
1722 gb->hdma_steps_left = (value & 0x7F) + 1;
1723 if ((value & 0x80) == 0 && gb->hdma_on_hblank) {
1724 gb->hdma_on_hblank = false;
1725 return;
1726 }
1727 gb->hdma_on = (value & 0x80) == 0;
1728 gb->hdma_on_hblank = (value & 0x80) != 0;
1729 if (gb->hdma_on_hblank && (gb->io_registers[GB_IO_STAT] & 3) == 0 && gb->display_state != 7) {
1730 gb->hdma_on = true;
1731 }
1732 return;
1733
1734 /* TODO: What happens when starting a transfer during external clock?
1735 TODO: When a cable is connected, the clock of the other side affects "zombie" serial clocking */
1736 case GB_IO_SC:
1737 gb->serial_count = 0;
1738 if (!gb->cgb_mode) {
1739 value |= 2;
1740 }
1741 if (gb->serial_master_clock) {
1742 GB_serial_master_edge(gb);
1743 }
1744 gb->io_registers[GB_IO_SC] = value | (~0x83);
1745 gb->serial_mask = gb->cgb_mode && (value & 2)? 4 : 0x80;
1746 if ((value & 0x80) && (value & 0x1) ) {
1747 if (gb->serial_transfer_bit_start_callback) {
1748 gb->serial_transfer_bit_start_callback(gb, gb->io_registers[GB_IO_SB] & 0x80);
1749 }
1750 }
1751
1752 return;
1753
1754 case GB_IO_RP: {
1755 if (!GB_is_cgb(gb)) {
1756 return;
1757 }
1758 if ((gb->io_registers[GB_IO_RP] ^ value) & 1) {
1759 if (gb->infrared_callback) {
1760 gb->infrared_callback(gb, value & 1);
1761 }
1762 }
1763 gb->io_registers[GB_IO_RP] = value;
1764
1765 return;
1766 }
1767
1768 default:
1769 if ((addr & 0xFF) >= GB_IO_NR10 && (addr & 0xFF) <= GB_IO_WAV_END) {
1770 GB_apu_write(gb, addr & 0xFF, value);
1771 return;
1772 }
1773 GB_log(gb, "Wrote %02x to %04x (HW Register)\n", value, addr);
1774 return;
1775 }
1776 }
1777
1778 if (addr == 0xFFFF) {
1779 GB_display_sync(gb);
1780 /* Interrupt mask */
1781 gb->interrupt_enable = value;
1782 return;
1783 }
1784
1785 /* HRAM */
1786 gb->hram[addr - 0xFF80] = value;
1787 }
1788
1789
1790
1791 static write_function_t *const write_map[] =
1792 {
1793 write_mbc, write_mbc, write_mbc, write_mbc, /* 0XXX, 1XXX, 2XXX, 3XXX */
1794 write_mbc, write_mbc, write_mbc, write_mbc, /* 4XXX, 5XXX, 6XXX, 7XXX */
1795 write_vram, write_vram, /* 8XXX, 9XXX */
1796 write_mbc_ram, write_mbc_ram, /* AXXX, BXXX */
1797 write_ram, write_banked_ram, /* CXXX, DXXX */
1798 write_ram, write_high_memory, /* EXXX FXXX */
1799 };
1800
1801 void GB_set_write_memory_callback(GB_gameboy_t *gb, GB_write_memory_callback_t callback)
1802 {
1803 if (!callback) {
1804 GB_ASSERT_NOT_RUNNING_OTHER_THREAD(gb)
1805 }
1806 gb->write_memory_callback = callback;
1807 }
1808
1809 void GB_write_memory(GB_gameboy_t *gb, uint16_t addr, uint8_t value)
1810 {
1811 GB_ASSERT_NOT_RUNNING_OTHER_THREAD(gb)
1812 #ifndef GB_DISABLE_DEBUGGER
1813 if (unlikely(gb->n_watchpoints)) {
1814 GB_debugger_test_write_watchpoint(gb, addr, value);
1815 }
1816 #endif
1817 if (bus_for_addr(gb, addr) == GB_BUS_MAIN && addr < 0xFF00) {
1818 gb->data_bus = value;
1819 gb->data_bus_decay_countdown = gb->data_bus_decay;
1820 }
1821
1822 if (unlikely(gb->write_memory_callback)) {
1823 if (!gb->write_memory_callback(gb, addr, value)) return;
1824 }
1825
1826 if (unlikely(is_addr_in_dma_use(gb, addr))) {
1827 bool oam_write = addr >= 0xFE00;
1828 if (GB_is_cgb(gb) && bus_for_addr(gb, addr) == GB_BUS_MAIN && gb->dma_current_src >= 0xE000) {
1829 /* This is cart specific! Everdrive 7X on a CGB-A or 0 behaves differently. */
1830 return;
1831 }
1832
1833 if (GB_is_cgb(gb) && (gb->dma_current_src < 0xC000 || gb->dma_current_src >= 0xE000) && addr >= 0xC000) {
1834 // TODO: this should probably affect the DMA dest as well
1835 addr = ((gb->dma_current_src - 1) & 0x1000) | (addr & 0xFFF) | 0xC000;
1836 goto write;
1837 }
1838 else if (GB_is_cgb(gb) && gb->dma_current_src >= 0xE000 && addr >= 0xC000) {
1839 // TODO: this should probably affect the DMA dest as well
1840 addr = ((gb->dma_current_src - 1) & 0x1000) | (addr & 0xFFF) | 0xC000;
1841 }
1842 else {
1843 addr = (gb->dma_current_src - 1);
1844 }
1845 if (GB_is_cgb(gb) || addr >= 0xA000) {
1846 if (addr < 0xA000) {
1847 gb->oam[gb->dma_current_dest - 1] = 0;
1848 }
1849 else if ((gb->model < GB_MODEL_CGB_0 || gb->model == GB_MODEL_CGB_B)) {
1850 gb->oam[gb->dma_current_dest - 1] &= value;
1851 }
1852 else if ((gb->model < GB_MODEL_CGB_C || gb->model > GB_MODEL_CGB_E) && !oam_write) {
1853 gb->oam[gb->dma_current_dest - 1] = value;
1854 }
1855 if (gb->model < GB_MODEL_CGB_E || addr >= 0xA000) return;
1856 }
1857 }
1858 write:
1859 write_map[addr >> 12](gb, addr, value);
1860 }
1861
1862 bool GB_is_dma_active(GB_gameboy_t *gb)
1863 {
1864 return gb->dma_current_dest != 0xA1;
1865 }
1866
1867 void GB_dma_run(GB_gameboy_t *gb)
1868 {
1869 if (gb->dma_current_dest == 0xA1) return;
1870 if (unlikely(gb->halted || gb->stopped)) return;
1871 signed cycles = gb->dma_cycles + gb->dma_cycles_modulo;
1872 gb->in_dma_read = true;
1873 while (unlikely(cycles >= 4)) {
1874 cycles -= 4;
1875 if (gb->dma_current_dest >= 0xA0) {
1876 gb->dma_current_dest++;
1877 if (gb->display_state == 8) {
1878 gb->io_registers[GB_IO_STAT] |= 2;
1879 GB_STAT_update(gb);
1880 }
1881 break;
1882 }
1883 if (unlikely(gb->hdma_in_progress && (gb->hdma_steps_left > 1 || (gb->hdma_current_dest & 0xF) != 0xF))) {
1884 gb->dma_current_dest++;
1885 }
1886 else if (gb->dma_current_src < 0xE000) {
1887 gb->oam[gb->dma_current_dest++] = GB_read_memory(gb, gb->dma_current_src);
1888 }
1889 else {
1890 if (GB_is_cgb(gb)) {
1891 gb->oam[gb->dma_current_dest++] = 0xFF;
1892 }
1893 else {
1894 gb->oam[gb->dma_current_dest++] = GB_read_memory(gb, gb->dma_current_src & ~0x2000);
1895 }
1896 }
1897
1898 /* dma_current_src must be the correct value during GB_read_memory */
1899 gb->dma_current_src++;
1900 gb->dma_ppu_vram_conflict = false;
1901 }
1902 gb->in_dma_read = false;
1903 gb->dma_cycles_modulo = cycles;
1904 gb->dma_cycles = 0;
1905 }
1906
1907 void GB_hdma_run(GB_gameboy_t *gb)
1908 {
1909 unsigned cycles = gb->cgb_double_speed? 4 : 2;
1910 /* TODO: This portion of code is probably inaccurate because it probably depends on my specific GB-Live32 */
1911 #if 0
1912 /* This is a bit cart, revision and unit specific. TODO: what if PC is in cart RAM? */
1913 if (gb->model < GB_MODEL_CGB_D || gb->pc > 0x8000) {
1914 gb->data_bus = 0xFF;
1915 }
1916 #endif
1917 gb->addr_for_hdma_conflict = 0xFFFF;
1918 uint16_t vram_base = gb->cgb_vram_bank? 0x2000 : 0;
1919 gb->hdma_in_progress = true;
1920 GB_advance_cycles(gb, cycles);
1921 while (gb->hdma_on) {
1922 uint8_t byte = gb->data_bus;
1923 gb->addr_for_hdma_conflict = 0xFFFF;
1924
1925 if (gb->hdma_current_src < 0x8000 ||
1926 (gb->hdma_current_src & 0xE000) == 0xC000 ||
1927 (gb->hdma_current_src & 0xE000) == 0xA000) {
1928 byte = GB_read_memory(gb, gb->hdma_current_src);
1929 }
1930 if (unlikely(GB_is_dma_active(gb)) && (gb->dma_cycles_modulo == 2 || gb->cgb_double_speed)) {
1931 write_oam(gb, gb->hdma_current_src, byte);
1932 }
1933 gb->hdma_current_src++;
1934 GB_advance_cycles(gb, cycles);
1935 if (gb->addr_for_hdma_conflict == 0xFFFF /* || ((gb->model & ~GB_MODEL_GBP_BIT) >= GB_MODEL_AGB_B && gb->cgb_double_speed) */) {
1936 uint16_t addr = (gb->hdma_current_dest++ & 0x1FFF);
1937 gb->vram[vram_base + addr] = byte;
1938 // TODO: vram_write_blocked might not be the correct timing
1939 if (gb->vram_write_blocked /* && (gb->model & ~GB_MODEL_GBP_BIT) < GB_MODEL_AGB_B */) {
1940 gb->vram[(vram_base ^ 0x2000) + addr] = byte;
1941 }
1942 }
1943 else {
1944 if (gb->model == GB_MODEL_CGB_E || gb->cgb_double_speed) {
1945 /*
1946 These corruptions revision (unit?) specific in single speed. They happen only on my CGB-E.
1947 */
1948 gb->addr_for_hdma_conflict &= 0x1FFF;
1949 // TODO: there are *some* scenarions in single speed mode where this write doesn't happen. What's the logic?
1950 uint16_t addr = (gb->hdma_current_dest & gb->addr_for_hdma_conflict & 0x1FFF);
1951 gb->vram[vram_base + addr] = byte;
1952 // TODO: vram_write_blocked might not be the correct timing
1953 if (gb->vram_write_blocked /* && (gb->model & ~GB_MODEL_GBP_BIT) < GB_MODEL_AGB_B */) {
1954 gb->vram[(vram_base ^ 0x2000) + addr] = byte;
1955 }
1956 }
1957 gb->hdma_current_dest++;
1958 }
1959
1960 if ((gb->hdma_current_dest & 0xF) == 0) {
1961 if (--gb->hdma_steps_left == 0 || gb->hdma_current_dest == 0) {
1962 gb->hdma_on = false;
1963 gb->hdma_on_hblank = false;
1964 }
1965 else if (gb->hdma_on_hblank) {
1966 gb->hdma_on = false;
1967 }
1968 }
1969 }
1970 gb->hdma_in_progress = false; // TODO: timing? (affects VRAM reads)
1971 if (!gb->cgb_double_speed) {
1972 GB_advance_cycles(gb, 2);
1973 }
1974 }
This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.