diff --git a/src/BizHawk.Emulation.Cores/Consoles/Watara/SuperVision/ASIC.cs b/src/BizHawk.Emulation.Cores/Consoles/Watara/SuperVision/ASIC.cs index 27024a646f..b4b14421fa 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Watara/SuperVision/ASIC.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Watara/SuperVision/ASIC.cs @@ -48,7 +48,12 @@ namespace BizHawk.Emulation.Cores.Consoles.SuperVision public int CLOCK_WIDTH => ((_regs[R_LCD_X_SIZE] & 0xFC) // topmost 6 bits of the X Size register + 4) // line latch pulse - * 6; // 6 clocks per pixel + * 6; // 6 clocks per pixel + + /// + /// Y offset modifier used with Y_Scroll to determine the VRAM pointer + /// + public int Y_OFFSET => _regs[R_LCD_X_SIZE] > 0xC0 ? 0x30 : 0x60; /// /// Number of scanlines in a field @@ -82,6 +87,8 @@ namespace BizHawk.Emulation.Cores.Consoles.SuperVision private int _lineCounter; private int _field; private ushort _vramByteBuffer; + private int _vramPointer; + private int _vramStartAddress; /// /// ASIC is clocked at the same rate as the CPU @@ -106,8 +113,29 @@ namespace BizHawk.Emulation.Cores.Consoles.SuperVision // there is no DMA on this cycle so CPU can run freely _sv._cpu.RDY = true; + bool lineEnd = _byteCounter == CLOCK_WIDTH - 1; + bool fieldEnd = _lineCounter == LINE_HEIGHT && lineEnd && _field == 0; + bool frameEnd = _lineCounter == LINE_HEIGHT && lineEnd && _field == 1; + + // vram pointer + if (fieldEnd) + { + // Y_Scroll offset added to the VRAM pointer at the start of the field (could be frame) + _vramStartAddress = (_regs[R_Y_SCROLL] * Y_OFFSET) & 0x1FFF; + + if (_vramStartAddress == 0x1FE0) + _vramStartAddress = 0; + } + + if (_byteCounter == 0) + { + // new scanline + _vramPointer = _vramStartAddress + (_regs[R_X_SCROLL] >> 2); + } + // ASIC reads a byte from VRAM - byte data = 0xff; //todo + byte data = _sv.ReadVRAM((ushort) _vramPointer); + _vramPointer++; // shift the last read byte in the buffer and add the new byte to the start _vramByteBuffer = (ushort) ((_vramByteBuffer << 8) | data); @@ -121,10 +149,7 @@ namespace BizHawk.Emulation.Cores.Consoles.SuperVision // Field1: bits 1-3-5-7 byte lData = _field == 0 ? (byte) ((b & 0b0000_0001) | ((b & 0b0000_0100) >> 1) | ((b & 0b0001_0000) >> 2) | ((b & 0b0100_0000) >> 3)) - : (byte) ((b & 0b0000_0010) >> 1 | ((b & 0b0000_1000) >> 2) | ((b & 0b0010_0000) >> 3) | ((b & 0b1000_0000) >> 4)); - - bool lineEnd = _byteCounter == CLOCK_WIDTH - 1; - bool frameEnd = _lineCounter == LINE_HEIGHT && lineEnd && _field == 1; + : (byte) ((b & 0b0000_0010) >> 1 | ((b & 0b0000_1000) >> 2) | ((b & 0b0010_0000) >> 3) | ((b & 0b1000_0000) >> 4)); // send 1/2 byte to the LCD Screen.PixelClock(lData, _field, lineEnd, frameEnd); @@ -137,6 +162,11 @@ namespace BizHawk.Emulation.Cores.Consoles.SuperVision _byteCounter = 0; _lineCounter++; + // setup start address + _vramStartAddress += Y_OFFSET & 0x1FFF; + if (_vramStartAddress == 0x1FE0) + _vramStartAddress = 0; + if (_lineCounter == LINE_HEIGHT) { // end of field @@ -395,7 +425,7 @@ namespace BizHawk.Emulation.Cores.Consoles.SuperVision Screen.DisplayEnable = value.Bit(3); // banking - _sv.BankSelect = value >> 5; + _sv.BankSelect = (value >> 5); // writing to this register resets the LCD rendering system and makes it start rendering from the upper left corner, regardless of the bit pattern. Screen.ResetPosition(); @@ -546,6 +576,8 @@ namespace BizHawk.Emulation.Cores.Consoles.SuperVision ser.Sync(nameof(_lineCounter), ref _lineCounter); ser.Sync(nameof(_field), ref _field); ser.Sync(nameof(_vramByteBuffer), ref _vramByteBuffer); + ser.Sync(nameof(_vramPointer), ref _vramPointer); + ser.Sync(nameof(_vramStartAddress), ref _vramStartAddress); Screen.SyncState(ser); ser.EndSection(); diff --git a/src/BizHawk.Emulation.Cores/Consoles/Watara/SuperVision/Cart/SVCart.cs b/src/BizHawk.Emulation.Cores/Consoles/Watara/SuperVision/Cart/SVCart.cs index 2420054454..a7e41741ad 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Watara/SuperVision/Cart/SVCart.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Watara/SuperVision/Cart/SVCart.cs @@ -10,6 +10,8 @@ namespace BizHawk.Emulation.Cores.Consoles.SuperVision /// private byte[] _rom = new byte[0x20000]; + public int CartROMSize => _rom.Length; + public SVCart(byte[] rom) { if (_rom.Length != rom.Length) diff --git a/src/BizHawk.Emulation.Cores/Consoles/Watara/SuperVision/Memory.cs b/src/BizHawk.Emulation.Cores/Consoles/Watara/SuperVision/Memory.cs index e153604621..1827582c4d 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Watara/SuperVision/Memory.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Watara/SuperVision/Memory.cs @@ -11,12 +11,18 @@ namespace BizHawk.Emulation.Cores.Consoles.SuperVision /// /// 8K of VRAM which the CPU can access with 0 wait states /// - public byte[] VRAM = new byte[0x2000]; + public byte[] VRAM = new byte[0x2000]; /// /// Bank select index /// - public int BankSelect; + public int BankSelect + { + get { return _bankSelect % (_cartridge.CartROMSize / 0x4000); } + set { _bankSelect = value; } + } + private int _bankSelect; + /// /// True when the CPU is accessing memory @@ -63,6 +69,7 @@ namespace BizHawk.Emulation.Cores.Consoles.SuperVision // 0: first 16k // 1: 2nd 16k // 2: 3rd 16k + // etc.. result = _cartridge.ReadByte((ushort) ((address % 0x4000) + (BankSelect * 0x4000))); break; @@ -71,7 +78,7 @@ namespace BizHawk.Emulation.Cores.Consoles.SuperVision case 6: case 7: // fixed to the last 16K in the cart address space - result = _cartridge.ReadByte((ushort) ((address % 0x4000) + (3 * 0x4000))); + result = _cartridge.ReadByte((ushort) ((address % 0x4000) + (_cartridge.CartROMSize - 0x4000))); break; } @@ -115,6 +122,7 @@ namespace BizHawk.Emulation.Cores.Consoles.SuperVision // 0: first 16k // 1: 2nd 16k // 2: 3rd 16k + // etc.. _cartridge.WriteByte((ushort) ((address % 0x4000) + (BankSelect * 0x4000)), value); break; @@ -123,9 +131,19 @@ namespace BizHawk.Emulation.Cores.Consoles.SuperVision case 6: case 7: // fixed to the last 16K in the cart address space - _cartridge.WriteByte((ushort) ((address % 0x4000) + (3 * 0x4000)), value); + _cartridge.WriteByte((ushort) ((address % 0x4000) + (_cartridge.CartROMSize - 0x4000)), value); break; } } + + /// + /// ASIC is connected directly to VRAM + /// 8bit data bus + /// 12bit addr bus + /// + public byte ReadVRAM(ushort address) + { + return VRAM[address & 0x0FFF]; + } } } diff --git a/src/BizHawk.Emulation.Cores/Consoles/Watara/SuperVision/SuperVision.Statable.cs b/src/BizHawk.Emulation.Cores/Consoles/Watara/SuperVision/SuperVision.Statable.cs index b86b557400..0f23f7bad3 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Watara/SuperVision/SuperVision.Statable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Watara/SuperVision/SuperVision.Statable.cs @@ -7,7 +7,7 @@ namespace BizHawk.Emulation.Cores.Consoles.SuperVision private void SyncState(Serializer ser) { ser.BeginSection("SuperVision"); - ser.Sync(nameof(BankSelect), ref BankSelect); + ser.Sync(nameof(BankSelect), ref _bankSelect); ser.Sync(nameof(_frameClock), ref _frameClock); ser.Sync(nameof(_frame), ref _frame);