From 22aec7c6c16be482370c98a983827624abb26c85 Mon Sep 17 00:00:00 2001 From: sinamas Date: Fri, 24 Oct 2008 08:19:15 +0000 Subject: [PATCH] No rambanks for ROMs that don't request any. Route invalid rombank addresses in non-power-of-2 number of rombanks cases to disabled area assuming ceiled power of 2 address bus. DMG window display disregards bg enable bit. git-svn-id: https://gambatte.svn.sourceforge.net/svnroot/gambatte@189 9dfb2916-2d38-0410-aef4-c5fe6c9ffc24 --- libgambatte/src/memory.cpp | 37 +++++++++++++++++++++++++------------ libgambatte/src/video.cpp | 27 +++++++++++++-------------- 2 files changed, 38 insertions(+), 26 deletions(-) diff --git a/libgambatte/src/memory.cpp b/libgambatte/src/memory.cpp index 6b45dc60..76fd6004 100644 --- a/libgambatte/src/memory.cpp +++ b/libgambatte/src/memory.cpp @@ -132,7 +132,7 @@ void Memory::loadState(const SaveState &state, const unsigned long oldCc) { next_serialtime = state.mem.next_serialtime; lastOamDmaUpdate = state.mem.lastOamDmaUpdate; minIntTime = state.mem.minIntTime; - rombank = state.mem.rombank % rombanks; + rombank = state.mem.rombank & (rombanks - 1); dmaSource = state.mem.dmaSource; dmaDestination = state.mem.dmaDestination; rambank = state.mem.rambank & (rambanks - 1); @@ -615,15 +615,15 @@ void Memory::setRombank() { } void Memory::setRambank() { + rmem[0xB] = rmem[0xA] = rsrambankptr = rdisabled_ram - 0xA000; + wmem[0xB] = wmem[0xA] = wsrambankptr = wdisabled_ram - 0xA000; + if (enable_ram) { if (rtc.getActive()) { wmem[0xB] = wmem[0xA] = rmem[0xB] = rmem[0xA] = wsrambankptr = rsrambankptr = NULL; - } else { + } else if (rambanks) { wmem[0xB] = rmem[0xB] = wmem[0xA] = rmem[0xA] = wsrambankptr = rsrambankptr = rambankdata + rambank * 0x2000ul - 0xA000; } - } else { - rmem[0xB] = rmem[0xA] = rsrambankptr = rdisabled_ram - 0xA000; - wmem[0xB] = wmem[0xA] = wsrambankptr = wdisabled_ram - 0xA000; } if (oamDmaArea1Lower == 0xA0) { @@ -1420,7 +1420,7 @@ void Memory::mbc_write(const unsigned P, const unsigned data) { return; case mbc5: rombank = (rombank & 0x100) | data; - rombank = rombank % rombanks; + rombank = rombank & (rombanks - 1); setRombank(); return; default: @@ -1448,7 +1448,7 @@ void Memory::mbc_write(const unsigned P, const unsigned data) { return; } - rombank = rombank % rombanks; + rombank = rombank & (rombanks - 1); setRombank(); break; //MBC1 writes ???? ??nn to area 0x4000-0x5FFF either to determine rambank to load, or upper 2 bits of the rombank number to load, depending on rom-mode. @@ -1464,7 +1464,7 @@ void Memory::mbc_write(const unsigned P, const unsigned data) { } rombank = (data & 0x03) << 5 | (rombank & 0x1F); - rombank = rombank % rombanks; + rombank = rombank & (rombanks - 1); setRombank(); return; case mbc3: @@ -1547,6 +1547,17 @@ static void enforce8bit(unsigned char *data, unsigned long sz) { *data++ &= 0xFF; } +static unsigned pow2ceil(unsigned n) { + --n; + n |= n >> 1; + n |= n >> 2; + n |= n >> 4; + n |= n >> 8; + ++n; + + return n; +} + bool Memory::loadROM(const char *romfile, const bool forceDmg) { romFilePath = romfile; @@ -1706,7 +1717,7 @@ bool Memory::loadROM(const char *romfile, const bool forceDmg) { printf("rombanks: %u\n", rombanks);*/ switch (header[0x0149]) { - case 0x00: /*cout << "No RAM\n"; rambankrom=0; break;*/ + case 0x00: /*cout << "No RAM\n";*/ rambanks = 0; break; case 0x01: /*cout << "2kB RAM\n";*/ /*rambankrom=1; break;*/ case 0x02: /*cout << "8kB RAM\n";*/ rambanks = 1; @@ -1728,8 +1739,8 @@ bool Memory::loadROM(const char *romfile, const bool forceDmg) { std::printf("rambanks: %u\n", rambanks); - rombanks = rom.size() / 0x4000; - std::printf("rombanks: %u\n", rombanks); + rombanks = pow2ceil(rom.size() / 0x4000); + std::printf("rombanks: %u\n", rom.size() / 0x4000); delete []memchunk; memchunk = new unsigned char[0x4000 + rombanks * 0x4000ul + rambanks * 0x2000ul + (isCgb() ? 0x8000 : 0x2000) + 0x4000]; @@ -1744,7 +1755,9 @@ bool Memory::loadROM(const char *romfile, const bool forceDmg) { std::memset(rdisabled_ram, 0xFF, 0x2000); rom.rewind(); - rom.read(reinterpret_cast(romdata[0]), rombanks * 0x4000ul); + rom.read(reinterpret_cast(romdata[0]), (rom.size() / 0x4000) * 0x4000ul); + // In case rombanks isn't a power of 2, allocate a disabled area for invalid rombank addresses. This is only based on speculation. + std::memset(romdata[0] + (rom.size() / 0x4000) * 0x4000ul, 0xFF, (rombanks - rom.size() / 0x4000) * 0x4000ul); enforce8bit(romdata[0], rombanks * 0x4000ul); if (rom.fail()) diff --git a/libgambatte/src/video.cpp b/libgambatte/src/video.cpp index 98d66b50..12fcc911 100644 --- a/libgambatte/src/video.cpp +++ b/libgambatte/src/video.cpp @@ -975,22 +975,21 @@ void LCD::dmg_draw(unsigned xpos, const unsigned ypos, const unsigned endX) { winYPos = /*ypos - wyReg.value()*/ 0; T *const bufLine = static_cast(dbuffer) + ypos * static_cast(dpitch); - - if (bgEnable) { - if (!(enableWindow && win.wxReader.wx() <= xpos + 7)) { + + if (!(enableWindow && win.wxReader.wx() <= xpos + 7)) { + const unsigned end = std::min(enableWindow ? win.wxReader.wx() - 7 : 160U, endX); + + if (bgEnable) { const unsigned fby = scReader.scy() + ypos /*& 0xFF*/; - const unsigned end = std::min(enableWindow ? win.wxReader.wx() - 7 : 160U, endX); - bg_drawPixels(bufLine, xpos, end, effectiveScx, bgTileMap + (fby & 0xF8) * 4, bgTileData + (fby & 7) * 2); - } - - if (enableWindow && endX + 7 > win.wxReader.wx()) { - const unsigned start = std::max(win.wxReader.wx() < 7 ? 0U : (win.wxReader.wx() - 7), xpos); - - bg_drawPixels(bufLine, start, endX, 7u - win.wxReader.wx(), wdTileMap + (winYPos & 0xF8) * 4, bgTileData + (winYPos & 7) * 2); - } - } else - std::fill_n(bufLine + xpos, endX - xpos, bgPalette[0]); + } else + std::fill_n(bufLine + xpos, end - xpos, bgPalette[0]); + } + + if (enableWindow && endX + 7 > win.wxReader.wx()) { + const unsigned start = std::max(win.wxReader.wx() < 7 ? 0U : (win.wxReader.wx() - 7), xpos); + bg_drawPixels(bufLine, start, endX, 7u - win.wxReader.wx(), wdTileMap + (winYPos & 0xF8) * 4, bgTileData + (winYPos & 7) * 2); + } if (endX == 160) { if (spriteEnable)