public static int rb(int addr) { switch (addr & 0xF000) { // ROM bank 0 case 0x0000: if (MMU._inbios) { if (addr < 0x0100) { return(MMU._bios[addr]); } else if (Z80._r.pc == 0x0100) { MMU._inbios = false; LOG.@out("MMU", "Leaving BIOS."); return(rb(addr)); } } else { return(MMU._rom[addr]); } break; case 0x1000: case 0x2000: case 0x3000: return(MMU._rom[addr]); // ROM bank 1 case 0x4000: case 0x5000: case 0x6000: case 0x7000: return(MMU._rom[MMU._romoffs + (addr & 0x3FFF)]); // VRAM case 0x8000: case 0x9000: return(GPU._vram[addr & 0x1FFF]); // External RAM case 0xA000: case 0xB000: return(MMU._eram[MMU._ramoffs + (addr & 0x1FFF)]); // Work RAM and echo case 0xC000: case 0xD000: case 0xE000: return(MMU._wram[addr & 0x1FFF]); // Everything else case 0xF000: switch (addr & 0x0F00) { // Echo RAM case 0x000: case 0x100: case 0x200: case 0x300: case 0x400: case 0x500: case 0x600: case 0x700: case 0x800: case 0x900: case 0xA00: case 0xB00: case 0xC00: case 0xD00: return(MMU._wram[addr & 0x1FFF]); // OAM case 0xE00: return(((addr & 0xFF) < 0xA0) ? GPU._oam[addr & 0xFF] : 0); // Zeropage RAM, I/O, interrupts case 0xF00: if (addr == 0xFFFF) { return(MMU._ie); } else if (addr > 0xFF7F) { return(MMU._zram[addr & 0x7F]); } else { switch (addr & 0xF0) { case 0x00: switch (addr & 0xF) { case 0: return(KEY.rb()); // JOYP case 4: case 5: case 6: case 7: return(TIMER.rb(addr)); case 15: return(MMU._if); // Interrupt flags default: return(0); } case 0x10: case 0x20: case 0x30: return(0); case 0x40: case 0x50: case 0x60: case 0x70: return(GPU.rb(addr)); } } break; } break; } throw new InvalidOperationException($"Unable to read address {addr}: Out of range."); }
public static void Reset() { LOG.reset(); GPU.reset(); MMU.reset(); Z80.reset(); KEY.reset(); TIMER.reset(); Z80._r.pc = 0x100; MMU._inbios = true; Z80._r.sp = 0xFFFE; Z80._r.h = 0x01; Z80._r.l = 0x4D; Z80._r.c = 0x13; Z80._r.e = 0xD8; Z80._r.a = 1; }
public static void reset() { GPU._vram = new int[8192]; GPU._oam = new int[160]; for (int i = 0; i < 4; i++) { GPU._palette.bg[i] = 255; GPU._palette.obj0[i] = 255; GPU._palette.obj1[i] = 255; } GPU._tilemap = new int[512, 8, 8]; LOG.@out("GPU", "Initialising screen."); GPU._canvas = new int[160, 144]; for (int i = 0; i < GPU._scrn.data.Length; i++) { GPU._scrn.data[i] = 255; } CopyScrnToCanvas(); GPU._curline = 0; GPU._curscan = 0; GPU._linemode = 2; GPU._modeclocks = 0; GPU._yscrl = 0; GPU._xscrl = 0; GPU._raster = 0; GPU._ints = 0; GPU._lcdon = 0; GPU._bgon = 0; GPU._objon = 0; GPU._winon = 0; GPU._objsize = 0; GPU._scanrow = new int[160]; for (int i = 0; i < 40; i++) { GPU._objdata[i] = new ObjData { y = -16, x = -8, tile = 0, palette = 0, yflip = 0, xflip = 0, prio = 0, num = i }; } // Set to values expected by BIOS, to start GPU._bgtilebase = 0x0000; GPU._bgmapbase = 0x1800; GPU._wintilebase = 0x1800; // TODO: doesn't seem to be used anywhere? LOG.@out("GPU", "Reset."); }