diff options
Diffstat (limited to 'src/gb.c')
| -rw-r--r-- | src/gb.c | 16 |
1 files changed, 14 insertions, 2 deletions
@@ -64,7 +64,19 @@ u8 gb_read(GB *gb, u16 addr) { if (addr == 0xFF02) return gb->sc | 0x7E; if (addr >= 0xFF04 && addr <= 0xFF07) return timer_read(gb, addr); if (addr == 0xFF0F) return gb->iff | 0xE0; - if (addr >= 0xFF10 && addr <= 0xFF3F) return 0xFF; // APU (stub) + if (addr >= 0xFF10 && addr <= 0xFF3F) { + // Register-level APU: return stored value OR'd with the bits that read + // back as 1 on real hardware (write-only / unused bits). NR50 (0xFF24) + // has mask 0x00, so it reads back exactly what was written, which is + // what the game's volume fade-out relies on. + static const u8 apu_or[0x30] = { + 0x80,0x3F,0x00,0xFF,0xBF, 0xFF, 0x3F,0x00,0xFF,0xBF, + 0x7F,0xFF,0x9F,0xFF,0xBF, 0xFF, 0xFF,0x00,0x00,0xBF, + 0x00,0x00,0x70, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* FF30-FF3F wave RAM: exact */ + }; + return gb->apu[addr - 0xFF10] | apu_or[addr - 0xFF10]; + } if (addr >= 0xFF40 && addr <= 0xFF4B) { if (addr == 0xFF46) return gb->dma; return ppu_read_reg(gb, addr); @@ -114,7 +126,7 @@ void gb_write(GB *gb, u16 addr, u8 val) { } if (addr >= 0xFF04 && addr <= 0xFF07) { timer_write(gb, addr, val); return; } if (addr == 0xFF0F) { gb->iff = val & 0x1F; return; } - if (addr >= 0xFF10 && addr <= 0xFF3F) return; // APU stub + if (addr >= 0xFF10 && addr <= 0xFF3F) { gb->apu[addr - 0xFF10] = val; return; } if (addr >= 0xFF40 && addr <= 0xFF4B) { if (addr == 0xFF46) { oam_dma(gb, val); return; } ppu_write_reg(gb, addr, val); |
