mirror of https://github.com/bsnes-emu/bsnes.git
386 lines
13 KiB
C++
386 lines
13 KiB
C++
auto PPU::readIO(uint32 addr) -> uint8 {
|
|
switch(addr) {
|
|
|
|
//DISPCNT
|
|
case 0x0400'0000: return (
|
|
Background::IO::mode << 0
|
|
| io.gameBoyColorMode << 3
|
|
| Background::IO::frame << 4
|
|
| objects.io.hblank << 5
|
|
| objects.io.mapping << 6
|
|
| io.forceBlank << 7
|
|
);
|
|
case 0x0400'0001: return (
|
|
bg0.io.enable << 0
|
|
| bg1.io.enable << 1
|
|
| bg2.io.enable << 2
|
|
| bg3.io.enable << 3
|
|
| objects.io.enable << 4
|
|
| window0.io.enable << 5
|
|
| window1.io.enable << 6
|
|
| window2.io.enable << 7
|
|
);
|
|
|
|
//GRSWP
|
|
case 0x0400'0002: return io.greenSwap;
|
|
case 0x0400'0003: return 0;
|
|
|
|
//DISPSTAT
|
|
case 0x0400'0004: return (
|
|
io.vblank << 0
|
|
| io.hblank << 1
|
|
| io.vcoincidence << 2
|
|
| io.irqvblank << 3
|
|
| io.irqhblank << 4
|
|
| io.irqvcoincidence << 5
|
|
);
|
|
case 0x0400'0005: return (
|
|
io.vcompare
|
|
);
|
|
|
|
//VCOUNT
|
|
case 0x0400'0006: return io.vcounter.byte(0);
|
|
case 0x0400'0007: return io.vcounter.byte(1);
|
|
|
|
//BG0CNT
|
|
case 0x0400'0008: return bg0.io.priority << 0 | bg0.io.characterBase << 2 | bg0.io.unused << 4 | bg0.io.mosaic << 6 | bg0.io.colorMode << 7;
|
|
case 0x0400'0009: return bg0.io.screenBase << 0 | bg0.io.affineWrap << 5 | bg0.io.screenSize << 6;
|
|
|
|
//BG1CNT
|
|
case 0x0400'000a: return bg1.io.priority << 0 | bg1.io.characterBase << 2 | bg1.io.unused << 4 | bg1.io.mosaic << 6 | bg1.io.colorMode << 7;
|
|
case 0x0400'000b: return bg1.io.screenBase << 0 | bg1.io.affineWrap << 5 | bg1.io.screenSize << 6;
|
|
|
|
//BG2CNT
|
|
case 0x0400'000c: return bg2.io.priority << 0 | bg2.io.characterBase << 2 | bg2.io.unused << 4 | bg2.io.mosaic << 6 | bg2.io.colorMode << 7;
|
|
case 0x0400'000d: return bg2.io.screenBase << 0 | bg2.io.affineWrap << 5 | bg2.io.screenSize << 6;
|
|
|
|
//BG3CNT
|
|
case 0x0400'000e: return bg3.io.priority << 0 | bg3.io.characterBase << 2 | bg3.io.unused << 4 | bg3.io.mosaic << 6 | bg3.io.colorMode << 7;
|
|
case 0x0400'000f: return bg3.io.screenBase << 0 | bg3.io.affineWrap << 5 | bg3.io.screenSize << 6;
|
|
|
|
//WININ0
|
|
case 0x0400'0048: return window0.io.active[BG0] << 0 | window0.io.active[BG1] << 1 | window0.io.active[BG2] << 2 | window0.io.active[BG3] << 3 | window0.io.active[OBJ] << 4 | window0.io.active[SFX] << 5;
|
|
|
|
//WININ1
|
|
case 0x0400'0049: return window1.io.active[BG0] << 0 | window1.io.active[BG1] << 1 | window1.io.active[BG2] << 2 | window1.io.active[BG3] << 3 | window1.io.active[OBJ] << 4 | window1.io.active[SFX] << 5;
|
|
|
|
//WINOUT
|
|
case 0x0400'004a: return window3.io.active[BG0] << 0 | window3.io.active[BG1] << 1 | window3.io.active[BG2] << 2 | window3.io.active[BG3] << 3 | window3.io.active[OBJ] << 4 | window3.io.active[SFX] << 5;
|
|
|
|
//WININ2
|
|
case 0x0400'004b: return window2.io.active[BG0] << 0 | window2.io.active[BG1] << 1 | window2.io.active[BG2] << 2 | window2.io.active[BG3] << 3 | window2.io.active[OBJ] << 4 | window2.io.active[SFX] << 5;
|
|
|
|
//MOSAIC (write-only)
|
|
|
|
//BLTCNT
|
|
case 0x0400'0050: return (
|
|
screen.io.blendAbove[BG0] << 0
|
|
| screen.io.blendAbove[BG1] << 1
|
|
| screen.io.blendAbove[BG2] << 2
|
|
| screen.io.blendAbove[BG3] << 3
|
|
| screen.io.blendAbove[OBJ] << 4
|
|
| screen.io.blendAbove[SFX] << 5
|
|
| screen.io.blendMode << 6
|
|
);
|
|
case 0x0400'0051: return (
|
|
screen.io.blendBelow[BG0] << 0
|
|
| screen.io.blendBelow[BG1] << 1
|
|
| screen.io.blendBelow[BG2] << 2
|
|
| screen.io.blendBelow[BG3] << 3
|
|
| screen.io.blendBelow[OBJ] << 4
|
|
| screen.io.blendBelow[SFX] << 5
|
|
);
|
|
|
|
//BLDALPHA
|
|
case 0x0400'0052: return screen.io.blendEVA;
|
|
case 0x0400'0053: return screen.io.blendEVB;
|
|
|
|
//BLDY (write-only)
|
|
|
|
}
|
|
|
|
return cpu.pipeline.fetch.instruction.byte(addr & 1);
|
|
}
|
|
|
|
auto PPU::writeIO(uint32 addr, uint8 data) -> void {
|
|
switch(addr) {
|
|
|
|
//DISPCNT
|
|
case 0x0400'0000:
|
|
Background::IO::mode = data.bits(0,2);
|
|
io.gameBoyColorMode = data.bit (3);
|
|
Background::IO::frame = data.bit (4);
|
|
objects.io.hblank = data.bit (5);
|
|
objects.io.mapping = data.bit (6);
|
|
io.forceBlank = data.bit (7);
|
|
return;
|
|
case 0x0400'0001:
|
|
bg0.io.enable = data.bit(0);
|
|
bg1.io.enable = data.bit(1);
|
|
bg2.io.enable = data.bit(2);
|
|
bg3.io.enable = data.bit(3);
|
|
objects.io.enable = data.bit(4);
|
|
window0.io.enable = data.bit(5);
|
|
window1.io.enable = data.bit(6);
|
|
window2.io.enable = data.bit(7);
|
|
//outside window is enabled whenever any inside window is enabled
|
|
window3.io.enable = (bool)data.bits(5,7);
|
|
return;
|
|
|
|
//GRSWP
|
|
case 0x0400'0002:
|
|
io.greenSwap = data.bit(0);
|
|
return;
|
|
case 0x0400'0003:
|
|
return;
|
|
|
|
//DISPSTAT
|
|
case 0x0400'0004:
|
|
io.irqvblank = data.bit(3);
|
|
io.irqhblank = data.bit(4);
|
|
io.irqvcoincidence = data.bit(5);
|
|
return;
|
|
case 0x0400'0005:
|
|
io.vcompare = data;
|
|
return;
|
|
|
|
//BG0CNT
|
|
case 0x0400'0008:
|
|
bg0.io.priority = data.bits(0,1);
|
|
bg0.io.characterBase = data.bits(2,3);
|
|
bg0.io.unused = data.bits(4,5);
|
|
bg0.io.mosaic = data.bit (6);
|
|
bg0.io.colorMode = data.bit (7);
|
|
return;
|
|
case 0x0400'0009:
|
|
bg0.io.screenBase = data.bits(0,4);
|
|
bg0.io.affineWrap = false;
|
|
bg0.io.screenSize = data.bits(6,7);
|
|
return;
|
|
|
|
//BG1CNT
|
|
case 0x0400'000a:
|
|
bg1.io.priority = data.bits(0,1);
|
|
bg1.io.characterBase = data.bits(2,3);
|
|
bg1.io.unused = data.bits(4,5);
|
|
bg1.io.mosaic = data.bit (6);
|
|
bg1.io.colorMode = data.bit (7);
|
|
return;
|
|
case 0x0400'000b:
|
|
bg1.io.screenBase = data.bits(0,4);
|
|
bg1.io.affineWrap = false;
|
|
bg1.io.screenSize = data.bits(6,7);
|
|
return;
|
|
|
|
//BG2CNT
|
|
case 0x0400'000c:
|
|
bg2.io.priority = data.bits(0,1);
|
|
bg2.io.characterBase = data.bits(2,3);
|
|
bg2.io.unused = data.bits(4,5);
|
|
bg2.io.mosaic = data.bit (6);
|
|
bg2.io.colorMode = data.bit (7);
|
|
return;
|
|
case 0x0400'000d:
|
|
bg2.io.screenBase = data.bits(0,4);
|
|
bg2.io.affineWrap = data.bit (5);
|
|
bg2.io.screenSize = data.bits(6,7);
|
|
return;
|
|
|
|
//BG3CNT
|
|
case 0x0400'000e:
|
|
bg3.io.priority = data.bits(0,1);
|
|
bg3.io.characterBase = data.bits(2,3);
|
|
bg3.io.unused = data.bits(4,5);
|
|
bg3.io.mosaic = data.bit (6);
|
|
bg3.io.colorMode = data.bit (7);
|
|
return;
|
|
case 0x0400'000f:
|
|
bg3.io.screenBase = data.bits(0,4);
|
|
bg3.io.affineWrap = data.bit (5);
|
|
bg3.io.screenSize = data.bits(6,7);
|
|
return;
|
|
|
|
//BG0HOFS
|
|
case 0x0400'0010: bg0.io.hoffset.bits(0,7) = data.bits(0,7); return;
|
|
case 0x0400'0011: bg0.io.hoffset.bit (8) = data.bit (0); return;
|
|
|
|
//BG0VOFS
|
|
case 0x0400'0012: bg0.io.voffset.bits(0,7) = data.bits(0,7); return;
|
|
case 0x0400'0013: bg0.io.voffset.bit (8) = data.bit (0); return;
|
|
|
|
//BG1HOFS
|
|
case 0x0400'0014: bg1.io.hoffset.bits(0,7) = data.bits(0,7); return;
|
|
case 0x0400'0015: bg1.io.hoffset.bit (8) = data.bit (0); return;
|
|
|
|
//BG1VOFS
|
|
case 0x0400'0016: bg1.io.voffset.bits(0,7) = data.bits(0,7); return;
|
|
case 0x0400'0017: bg1.io.voffset.bit (8) = data.bit (0); return;
|
|
|
|
//BG2HOFS
|
|
case 0x0400'0018: bg2.io.hoffset.bits(0,7) = data.bits(0,7); return;
|
|
case 0x0400'0019: bg2.io.hoffset.bit (8) = data.bit (0); return;
|
|
|
|
//BG2VOFS
|
|
case 0x0400'001a: bg2.io.voffset.bits(0,7) = data.bits(0,7); return;
|
|
case 0x0400'001b: bg2.io.voffset.bit (8) = data.bit (0); return;
|
|
|
|
//BG3HOFS
|
|
case 0x0400'001c: bg3.io.hoffset.bits(0,7) = data.bits(0,7); return;
|
|
case 0x0400'001d: bg3.io.hoffset.bit (8) = data.bit (0); return;
|
|
|
|
//BG3VOFS
|
|
case 0x0400'001e: bg3.io.voffset.bits(0,7) = data.bits(0,7); return;
|
|
case 0x0400'001f: bg3.io.voffset.bit (8) = data.bit (0); return;
|
|
|
|
//BG2PA
|
|
case 0x0400'0020: bg2.io.pa.byte(0) = data; return;
|
|
case 0x0400'0021: bg2.io.pa.byte(1) = data; return;
|
|
|
|
//BG2PB
|
|
case 0x0400'0022: bg2.io.pb.byte(0) = data; return;
|
|
case 0x0400'0023: bg2.io.pb.byte(1) = data; return;
|
|
|
|
//BG2PC
|
|
case 0x0400'0024: bg2.io.pc.byte(0) = data; return;
|
|
case 0x0400'0025: bg2.io.pc.byte(1) = data; return;
|
|
|
|
//BG2PD
|
|
case 0x0400'0026: bg2.io.pd.byte(0) = data; return;
|
|
case 0x0400'0027: bg2.io.pd.byte(1) = data; return;
|
|
|
|
//BG2X
|
|
case 0x0400'0028: bg2.io.x.bits( 0, 7) = data.bits(0,7); bg2.io.lx = bg2.io.x; return;
|
|
case 0x0400'0029: bg2.io.x.bits( 8,15) = data.bits(0,7); bg2.io.lx = bg2.io.x; return;
|
|
case 0x0400'002a: bg2.io.x.bits(16,23) = data.bits(0,7); bg2.io.lx = bg2.io.x; return;
|
|
case 0x0400'002b: bg2.io.x.bits(24,27) = data.bits(0,3); bg2.io.lx = bg2.io.x; return;
|
|
|
|
//BG2Y
|
|
case 0x0400'002c: bg2.io.y.bits( 0, 7) = data.bits(0,7); bg2.io.ly = bg2.io.y; return;
|
|
case 0x0400'002d: bg2.io.y.bits( 8,15) = data.bits(0,7); bg2.io.ly = bg2.io.y; return;
|
|
case 0x0400'002e: bg2.io.y.bits(16,23) = data.bits(0,7); bg2.io.ly = bg2.io.y; return;
|
|
case 0x0400'002f: bg2.io.y.bits(24,27) = data.bits(0,3); bg2.io.ly = bg2.io.y; return;
|
|
|
|
//BG3PA
|
|
case 0x0400'0030: bg3.io.pa.byte(0) = data; return;
|
|
case 0x0400'0031: bg3.io.pa.byte(1) = data; return;
|
|
|
|
//BG3PB
|
|
case 0x0400'0032: bg3.io.pb.byte(0) = data; return;
|
|
case 0x0400'0033: bg3.io.pb.byte(1) = data; return;
|
|
|
|
//BG3PC
|
|
case 0x0400'0034: bg3.io.pc.byte(0) = data; return;
|
|
case 0x0400'0035: bg3.io.pc.byte(1) = data; return;
|
|
|
|
//BG3PD
|
|
case 0x0400'0036: bg3.io.pd.byte(0) = data; return;
|
|
case 0x0400'0037: bg3.io.pd.byte(1) = data; return;
|
|
|
|
//BG3X
|
|
case 0x0400'0038: bg3.io.x.bits( 0, 7) = data.bits(0,7); bg3.io.lx = bg3.io.x; return;
|
|
case 0x0400'0039: bg3.io.x.bits( 8,15) = data.bits(0,7); bg3.io.lx = bg3.io.x; return;
|
|
case 0x0400'003a: bg3.io.x.bits(16,23) = data.bits(0,7); bg3.io.lx = bg3.io.x; return;
|
|
case 0x0400'003b: bg3.io.x.bits(24,27) = data.bits(0,3); bg3.io.lx = bg3.io.x; return;
|
|
|
|
//BG3Y
|
|
case 0x0400'003c: bg3.io.y.bits( 0, 7) = data.bits(0,7); bg3.io.ly = bg3.io.y; return;
|
|
case 0x0400'003d: bg3.io.y.bits( 8,15) = data.bits(0,7); bg3.io.ly = bg3.io.y; return;
|
|
case 0x0400'003e: bg3.io.y.bits(16,23) = data.bits(0,7); bg3.io.ly = bg3.io.y; return;
|
|
case 0x0400'003f: bg3.io.y.bits(24,27) = data.bits(0,3); bg3.io.ly = bg3.io.y; return;
|
|
|
|
//WIN0H
|
|
case 0x0400'0040: window0.io.x2 = data; return;
|
|
case 0x0400'0041: window0.io.x1 = data; return;
|
|
|
|
//WIN1H
|
|
case 0x0400'0042: window1.io.x2 = data; return;
|
|
case 0x0400'0043: window1.io.x1 = data; return;
|
|
|
|
//WIN0V
|
|
case 0x0400'0044: window0.io.y2 = data; return;
|
|
case 0x0400'0045: window0.io.y1 = data; return;
|
|
|
|
//WIN1V
|
|
case 0x0400'0046: window1.io.y2 = data; return;
|
|
case 0x0400'0047: window1.io.y1 = data; return;
|
|
|
|
//WININ0
|
|
case 0x0400'0048:
|
|
window0.io.active[BG0] = data.bit(0);
|
|
window0.io.active[BG1] = data.bit(1);
|
|
window0.io.active[BG2] = data.bit(2);
|
|
window0.io.active[BG3] = data.bit(3);
|
|
window0.io.active[OBJ] = data.bit(4);
|
|
window0.io.active[SFX] = data.bit(5);
|
|
return;
|
|
|
|
//WININ1
|
|
case 0x0400'0049:
|
|
window1.io.active[BG0] = data.bit(0);
|
|
window1.io.active[BG1] = data.bit(1);
|
|
window1.io.active[BG2] = data.bit(2);
|
|
window1.io.active[BG3] = data.bit(3);
|
|
window1.io.active[OBJ] = data.bit(4);
|
|
window1.io.active[SFX] = data.bit(5);
|
|
return;
|
|
|
|
//WINOUT
|
|
case 0x0400'004a:
|
|
window3.io.active[BG0] = data.bit(0);
|
|
window3.io.active[BG1] = data.bit(1);
|
|
window3.io.active[BG2] = data.bit(2);
|
|
window3.io.active[BG3] = data.bit(3);
|
|
window3.io.active[OBJ] = data.bit(4);
|
|
window3.io.active[SFX] = data.bit(5);
|
|
return;
|
|
|
|
//WININ2
|
|
case 0x0400'004b:
|
|
window2.io.active[BG0] = data.bit(0);
|
|
window2.io.active[BG1] = data.bit(1);
|
|
window2.io.active[BG2] = data.bit(2);
|
|
window2.io.active[BG3] = data.bit(3);
|
|
window2.io.active[OBJ] = data.bit(4);
|
|
window2.io.active[SFX] = data.bit(5);
|
|
return;
|
|
|
|
//MOSAIC
|
|
case 0x0400'004c:
|
|
Background::IO::mosaicWidth = data.bits(0,3);
|
|
Background::IO::mosaicHeight = data.bits(4,7);
|
|
return;
|
|
case 0x0400'004d:
|
|
objects.io.mosaicWidth = data.bits(0,3);
|
|
objects.io.mosaicHeight = data.bits(4,7);
|
|
return;
|
|
|
|
//BLDCNT
|
|
case 0x0400'0050:
|
|
screen.io.blendAbove[BG0] = data.bit (0);
|
|
screen.io.blendAbove[BG1] = data.bit (1);
|
|
screen.io.blendAbove[BG2] = data.bit (2);
|
|
screen.io.blendAbove[BG3] = data.bit (3);
|
|
screen.io.blendAbove[OBJ] = data.bit (4);
|
|
screen.io.blendAbove[SFX] = data.bit (5);
|
|
screen.io.blendMode = data.bits(6,7);
|
|
return;
|
|
case 0x0400'0051:
|
|
screen.io.blendBelow[BG0] = data.bit(0);
|
|
screen.io.blendBelow[BG1] = data.bit(1);
|
|
screen.io.blendBelow[BG2] = data.bit(2);
|
|
screen.io.blendBelow[BG3] = data.bit(3);
|
|
screen.io.blendBelow[OBJ] = data.bit(4);
|
|
screen.io.blendBelow[SFX] = data.bit(5);
|
|
return;
|
|
|
|
//BLDALPHA
|
|
case 0x0400'0052: screen.io.blendEVA = data.bits(0,4); return;
|
|
case 0x0400'0053: screen.io.blendEVB = data.bits(0,4); return;
|
|
|
|
//BLDY
|
|
case 0x0400'0054: screen.io.blendEVY = data.bits(0,4); return;
|
|
case 0x0400'0055: return;
|
|
|
|
}
|
|
}
|