git.y1.nz

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.