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);