diff --git a/src/BizHawk.Client.Common/movie/PlatformFrameRates.cs b/src/BizHawk.Client.Common/movie/PlatformFrameRates.cs
index 226da42757..4f80cf6868 100644
--- a/src/BizHawk.Client.Common/movie/PlatformFrameRates.cs
+++ b/src/BizHawk.Client.Common/movie/PlatformFrameRates.cs
@@ -72,7 +72,7 @@ namespace BizHawk.Client.Common
["INTV"] = 59.92,
["ZXSpectrum_PAL"] = 50.080128205,
- ["AmstradCPC_PAL"] = 50.08012820512821, // = 1 / ((1024 * 312) / 16,000,000)
+ ["AmstradCPC_PAL"] = 50.08012820512821, // = 1 / ((1024 * 312) / 16,000,000)
["UZE"] = 1125000.0 / 18733.0, // = 8 * 315000000 / 88 / 1820 / 262 ≈ 60.05444936742646666
["VEC"] = 50,
@@ -82,8 +82,10 @@ namespace BizHawk.Client.Common
["TIC80"] = 60,
["ChannelF"] = 234375.0 / 3872.0, // (NTSCCarrier * 8 / 7) / (256 * 264)
- // note: ChannelF II PAL timings might be slightly different...
+ // note: ChannelF II PAL timings might be slightly different...
["ChannelF_PAL"] = 15625.0 / 312.0, // 4000000 / (256 * 312)
+
+ ["SuperVision"] = 50.08012820512821
};
public static double GetFrameRate(string systemId, bool pal)
diff --git a/src/BizHawk.Emulation.Common/SystemLookup.cs b/src/BizHawk.Emulation.Common/SystemLookup.cs
index 5332a73c3d..0af8499047 100644
--- a/src/BizHawk.Emulation.Common/SystemLookup.cs
+++ b/src/BizHawk.Emulation.Common/SystemLookup.cs
@@ -34,7 +34,8 @@ namespace BizHawk.Emulation.Common
new(VSystemID.Raw.O2, "Odyssey2"),
new(VSystemID.Raw.VEC, "Vectrex"),
new(VSystemID.Raw.MSX, "MSX"),
- new(VSystemID.Raw.NDS, "Nintendo DS")
+ new(VSystemID.Raw.NDS, "Nintendo DS"),
+ new(VSystemID.Raw.SuperVision, "Watara SuperVision")
};
public SystemInfo this[string systemId]
diff --git a/src/BizHawk.Emulation.Cores/Consoles/Watara/SuperVision/ASIC.Video.cs b/src/BizHawk.Emulation.Cores/Consoles/Watara/SuperVision/ASIC.Video.cs
deleted file mode 100644
index 05afc6b06a..0000000000
--- a/src/BizHawk.Emulation.Cores/Consoles/Watara/SuperVision/ASIC.Video.cs
+++ /dev/null
@@ -1,63 +0,0 @@
-namespace BizHawk.Emulation.Cores.Consoles.SuperVision
-{
- public partial class ASIC
- {
- ///
- /// The inbuilt LCD screen
- ///
- private LCD _screen;
-
- ///
- /// The current field being drawn (0 or 1)
- ///
- private int _field;
-
- ///
- /// VRAM byte read every 6 CPU cycles
- ///
- private byte _latchedVRAM;
-
- ///
- /// The current VRAM pointer - latched every 6 cpu cycles
- ///
- private int _currentVRAMPointer;
-
- private int _currY;
- private int _currX;
-
- private void SetupScreen(SuperVision.SuperVisionSyncSettings superVisionSyncSettings)
- {
- _screen = new LCD(superVisionSyncSettings.ScreenType);
- }
-
- private void VideoClock()
- {
- if (FrameStart)
- {
- // initial V start value (limit to 8k size)
- _currentVRAMPointer = (_regs[R_Y_SCROLL] * 0x30) * 0x1FFF;
- }
- else
- {
- _currentVRAMPointer++;
-
- if (_currentVRAMPointer == 0x1FE0)
- {
- // wrap around
- _currentVRAMPointer = 0;
- }
- }
-
- if (_sv.FrameClock % 6 == 0)
- {
- // address lines are updated with a new VRAM address
- _latchedVRAM = _sv.VRAM[_currentVRAMPointer];
-
-
-
- }
-
-
- }
- }
-}
diff --git a/src/BizHawk.Emulation.Cores/Consoles/Watara/SuperVision/ASIC.cs b/src/BizHawk.Emulation.Cores/Consoles/Watara/SuperVision/ASIC.cs
index b049fb6dda..169421dad5 100644
--- a/src/BizHawk.Emulation.Cores/Consoles/Watara/SuperVision/ASIC.cs
+++ b/src/BizHawk.Emulation.Cores/Consoles/Watara/SuperVision/ASIC.cs
@@ -41,37 +41,141 @@ namespace BizHawk.Emulation.Cores.Consoles.SuperVision
public const int R_SYSTEM_CONTROL = 0x26;
public const int R_IRQ_STATUS = 0x27;
- private SuperVision _sv;
+ ///
+ /// Scanline length in cpu clocks
+ ///
+ 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
+ ///
+ /// Number of scanlines in a field
+ ///
+ public int LINE_HEIGHT => _regs[R_LCD_Y_SIZE];
+
+ private SuperVision _sv;
private byte[] _regs = new byte[0x30];
+ ///
+ /// The inbuilt LCD screen
+ ///
+ public LCD Screen;
+
public ASIC(SuperVision sv, SuperVision.SuperVisionSyncSettings ss)
{
_sv = sv;
- _screen = new LCD(ss.ScreenType);
+ Screen = new LCD(ss.ScreenType);
}
public bool FrameStart;
private int _intTimer;
+ private bool _intTimerEnabled;
+ private bool _intTimerChanged;
private int _nmiTimer;
private bool _intFlag;
private bool _dmaInProgress;
private int _dmaCounter;
+ private int _seqCounter;
+ private int _byteCounter;
+ private int _lineCounter;
+ private int _field;
+ private ushort _vramByteBuffer;
///
/// ASIC is clocked at the same rate as the CPU
///
public void Clock()
{
- CheckInterrupt();
+ // According to the information presented in https://github.com/GrenderG/supervision_reveng_notes/blob/master/Supervision_Tech.txt
+ // it can be surmised that the ASIC rigidly sticks to a 6-phase sequencer, which is as follows:
+ // 0: CPU RDY line true / PixelCLK to LCD / Output 1/2 byte to LCD
+ // 1: DMA byte transfer to VRAM (if DMA is active) / CPU RDY line false (if DMA is active)
+ // 2: DMA byte transfer to VRAM (if DMA is active) / CPU RDY line false (if DMA is active)
+ // 3: DMA byte transfer to VRAM (if DMA is active) / CPU RDY line false (if DMA is active)
+ // 4: DMA byte transfer to VRAM (if DMA is active) / CPU RDY line false (if DMA is active)
+ // 5: DMA byte transfer to VRAM (if DMA is active) / CPU RDY line false (if DMA is active)
+
CheckDMA();
- VideoClock();
+
+ // so DMA can transfer 5 bytes to VRAM every 6 clocks, the 6th clock being the 1/2 byte transfer to the LCD
+ switch (_seqCounter)
+ {
+ case 0:
+ // there is no DMA on this cycle so CPU can run freely
+ _sv._cpu.RDY = true;
+
+ // ASIC reads a byte from VRAM
+ byte data = 0xff; //todo
+
+ // shift the last read byte in the buffer and add the new byte to the start
+ _vramByteBuffer = (ushort) ((_vramByteBuffer << 8) | data);
+
+ // get the correct byte data based on the X Scroll register lower 2 bits
+ // this simulates a delay in the bits sent to the LCD
+ byte b = (byte) ((_vramByteBuffer >> (_regs[R_X_SCROLL] & 0b0000_0011)) & 0xff);
+
+ // depending on the field, a 4 bit sequence is sent to the LCD
+ // Field0: bits 0-2-4-6
+ // 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;
+
+ // send 1/2 byte to the LCD
+ Screen.PixelClock(lData, _field, lineEnd, frameEnd);
+
+ _byteCounter++;
+
+ if (_byteCounter == CLOCK_WIDTH)
+ {
+ // end of scanline
+ _byteCounter = 0;
+ _lineCounter++;
+
+ if (_lineCounter == LINE_HEIGHT)
+ {
+ // end of field
+ _lineCounter = 0;
+ _field++;
+
+ if (_field == 2)
+ _field = 0; // wraparound
+ }
+ }
+ break;
+
+ default:
+ if (_dmaInProgress)
+ {
+ // perform DMA transfer
+ DoDMA();
+
+ _sv._cpu.RDY = !_dmaInProgress;
+ }
+ break;
+ }
+
+ _seqCounter++;
+
+ if (_seqCounter == 7)
+ _seqCounter = 0; // wraparound
+
+ CheckInterrupt();
AudioClock();
if (FrameStart)
FrameStart = false;
+
+ _sv.FrameClock++;
}
+ ///
+ /// The current prescaler value for the IRQ timer
+ ///
private int IntPrescaler => _regs[R_SYSTEM_CONTROL].Bit(4) ? 16384 : 256;
///
@@ -88,16 +192,63 @@ namespace BizHawk.Emulation.Cores.Consoles.SuperVision
_sv._cpu.NMI = true;
}
- _intTimer--;
-
- if (_intTimer <= 0)
+ if (_intTimerChanged)
{
+ // IRQ timer register has just been modified
+ _intTimerChanged = false;
+ _intTimerEnabled = true;
+ // prescaler reset
+ _intTimer = 0;
+
+ if (_regs[R_IRQ_TIMER] == 0)
+ {
+ if (_regs[R_SYSTEM_CONTROL].Bit(1))
+ {
+ // instant IRQ
+ _intFlag = true;
+ _intTimerEnabled = false;
+
+ // set IRQ Timer expired bit
+ _regs[R_IRQ_STATUS] = (byte) (_regs[R_IRQ_STATUS] | 2);
+ }
+ }
+ }
+ else if (_regs[R_IRQ_TIMER] > 0)
+ {
+ // timer will be counting down clocked by the prescaler
+ if (_intTimer++ == IntPrescaler)
+ {
+ // prescaler clock
+ _intTimer = 0;
+
+ // decrement timer
+ _regs[R_IRQ_TIMER]--;
+ }
+ }
+ else
+ {
+ // timer has expired
+ if (_intTimerEnabled)
+ {
+ _intFlag = true;
+ _intTimerEnabled = false;
+
+ // set IRQ Timer expired bit
+ _regs[R_IRQ_STATUS] = (byte) (_regs[R_IRQ_STATUS] | 2);
+ }
+ }
+
+ if (_intFlag && _regs[R_SYSTEM_CONTROL].Bit(1))
+ {
+ // IRQ enabled
+ _sv._cpu.IRQ = true;
+ _intFlag = false;
}
}
///
- /// DMA Control
+ /// Check whether DMA needs to start
///
private void CheckDMA()
{
@@ -105,22 +256,46 @@ namespace BizHawk.Emulation.Cores.Consoles.SuperVision
{
// DMA start requested
_dmaInProgress = true;
- }
+ // Unset the DMA start bit
+ _regs[R_DMA_CONTROL] = (byte) (_regs[R_DMA_CONTROL] & ~(1 << 7));
+ }
+ }
+
+ ///
+ /// Perform a DMA transfer
+ ///
+ private void DoDMA()
+ {
if (_dmaInProgress)
{
- ushort source = (ushort) (_regs[R_DMA_SOURCE_HIGH] << 8 | _regs[R_DMA_SOURCE_LOW]);
- ushort dest = (ushort) (_regs[R_DMA_DEST_HIGH] << 8 | _regs[R_DMA_DEST_LOW]);
-
_dmaCounter++;
- if (_dmaCounter == 4096)
+ if (_dmaCounter == 4096 || _dmaCounter == _regs[R_DMA_LENGTH] * 16)
{
- // wrap around
+ // wraparound or length reached
_dmaCounter = 0;
+ _dmaInProgress = false;
+ }
+ else
+ {
+ ushort source = (ushort) (_regs[R_DMA_SOURCE_HIGH] << 8 | _regs[R_DMA_SOURCE_LOW]);
+ ushort dest = (ushort) (_regs[R_DMA_DEST_HIGH] << 8 | _regs[R_DMA_DEST_LOW]);
+
+ // transfer a byte from source to dest using DMA
+ _sv.WriteMemory(dest, _sv.ReadMemory(source));
+
+ // source registers incremented
+ source++;
+ _regs[R_DMA_SOURCE_HIGH] = (byte) (source >> 8);
+ _regs[R_DMA_SOURCE_LOW] = (byte) source;
+
+ // destination registers incremeneted
+ dest++;
+ _regs[R_DMA_DEST_HIGH] = (byte) (dest >> 8);
+ _regs[R_DMA_DEST_LOW] = (byte) dest;
}
}
-
}
///
@@ -135,45 +310,83 @@ namespace BizHawk.Emulation.Cores.Consoles.SuperVision
// LCD_X_Size
case 0x00:
case 0x04:
+
+ // Only the upper 6 bits of LCD_X_Size are usable. The lower 2 bits are ignored.
+ // the LCD size can only be changed in 4 pixel increments
+ _regs[R_LCD_X_SIZE] = value;
+
break;
// LCD_Y_Size
case 0x01:
case 0x05:
+
+ // LCD_Y_Size controls how many scanlines are shown in the field
+ // After the requisite number of scanlines, the LCD frame latch signal is output and the frame polarity line is toggled
+ _regs[R_LCD_Y_SIZE] = value;
+
break;
// X_Scroll
case 0x02:
case 0x06:
+
+ _regs[R_X_SCROLL] = value;
+
break;
// Y_Scroll
case 0x03:
case 0x07:
+
+ _regs[R_Y_SCROLL] = value;
+
break;
// DMA Source low
case 0x08:
+
+ _regs[R_DMA_SOURCE_LOW] = value;
+
break;
// DMA Source high
case 0x09:
+
+ _regs[R_DMA_SOURCE_HIGH] = value;
+
break;
// DMA Destination low
case 0x0A:
+
+ _regs[R_DMA_DEST_LOW] = value;
+
break;
// DMA Destination high
case 0x0B:
+
+ _regs[R_DMA_DEST_HIGH] = value;
+
break;
// DMA Length
case 0x0C:
+
+ // 8bit register
+ // This register selects how many bytes of data to move. The actual number of bytes to move is (L * 16).
+ // If the register is loaded with 0, a full 4096 bytes is moved.
+ _regs[R_DMA_LENGTH] = value;
+
break;
// DMA Control
case 0x0D:
+
+ // Start DMA when written with bit7 set
+ _regs[R_DMA_CONTROL] = value;
+
break;
// CH1_Flow (right only)
@@ -244,9 +457,12 @@ namespace BizHawk.Emulation.Cores.Consoles.SuperVision
// This timer is clocked by a prescaler, which is reset when the timer is written to.
// This prescaler can divide the system clock by 256 or 16384.
// 8bits
+ _regs[R_IRQ_TIMER] = value;
+
+ _intTimerEnabled = true;
// reset prescaler?
- _regs[R_SYSTEM_CONTROL] = (byte)(_regs[R_SYSTEM_CONTROL] & ~(1 << 4)); // Reset bit 4
+ //_regs[R_SYSTEM_CONTROL] = (byte)(_regs[R_SYSTEM_CONTROL] & ~(1 << 4)); // Reset bit 4
_intTimer = value * IntPrescaler;
@@ -274,20 +490,16 @@ namespace BizHawk.Emulation.Cores.Consoles.SuperVision
_regs[regIndex] = value;
// lcd displayenable
- _screen.DisplayEnable = value.Bit(3);
+ Screen.DisplayEnable = value.Bit(3);
// banking
_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();
+ Screen.ResetPosition();
break;
- // IRQ status
- case 0x27:
- break;
-
// CH4_Freq_Vol (left and right)
case 0x28:
case 0x2C:
@@ -305,7 +517,8 @@ namespace BizHawk.Emulation.Cores.Consoles.SuperVision
// READONLY
- case 0x20: // Controller
+ case 0x20: // Controller
+ case 0x27: // IRQ status
break;
// UNKNOWN
@@ -440,6 +653,7 @@ namespace BizHawk.Emulation.Cores.Consoles.SuperVision
// IRQ timer
case 0x23:
+ result = _regs[R_IRQ_TIMER];
break;
// Reset IRQ timer flag
@@ -457,6 +671,11 @@ namespace BizHawk.Emulation.Cores.Consoles.SuperVision
// IRQ status
case 0x27:
+
+ // bit0: DMA Audio System (1 == DMA audio finished)
+ // bit1: IRQ Timer expired (1 == expired)
+ result = _regs[regIndex];
+
break;
// CH4_Freq_Vol (left and right)
@@ -500,18 +719,18 @@ namespace BizHawk.Emulation.Cores.Consoles.SuperVision
ser.Sync(nameof(_regs), ref _regs, false);
ser.Sync(nameof(FrameStart), ref FrameStart);
ser.Sync(nameof(_intTimer), ref _intTimer);
+ ser.Sync(nameof(_intTimerEnabled), ref _intTimerEnabled);
+ ser.Sync(nameof(_intTimerChanged), ref _intTimerChanged);
ser.Sync(nameof(_nmiTimer), ref _nmiTimer);
ser.Sync(nameof(_intFlag), ref _intFlag);
ser.Sync(nameof(_dmaInProgress), ref _dmaInProgress);
ser.Sync(nameof(_dmaCounter), ref _dmaCounter);
-
+ ser.Sync(nameof(_seqCounter), ref _seqCounter);
+ ser.Sync(nameof(_byteCounter), ref _byteCounter);
+ ser.Sync(nameof(_lineCounter), ref _lineCounter);
ser.Sync(nameof(_field), ref _field);
- ser.Sync(nameof(_latchedVRAM), ref _latchedVRAM);
- ser.Sync(nameof(_currentVRAMPointer), ref _currentVRAMPointer);
- ser.Sync(nameof(_currY), ref _currY);
- ser.Sync(nameof(_currX), ref _currX);
-
- _screen.SyncState(ser);
+ ser.Sync(nameof(_vramByteBuffer), ref _vramByteBuffer);
+ Screen.SyncState(ser);
ser.EndSection();
}
diff --git a/src/BizHawk.Emulation.Cores/Consoles/Watara/SuperVision/LCD.cs b/src/BizHawk.Emulation.Cores/Consoles/Watara/SuperVision/LCD.cs
index 0469220df4..86d9655bbf 100644
--- a/src/BizHawk.Emulation.Cores/Consoles/Watara/SuperVision/LCD.cs
+++ b/src/BizHawk.Emulation.Cores/Consoles/Watara/SuperVision/LCD.cs
@@ -27,10 +27,13 @@ namespace BizHawk.Emulation.Cores.Consoles.SuperVision
private readonly int[] _palette = new int[4];
+ public const int PEN_BUFFER_WIDTH = 160 * 2;
+ public const int PEN_BUFFER_HEIGHT = 160;
+
///
/// The inbuilt screen is a 160*160 dot 2bpp monochrome LCD
///
- private int[] _penBuffer = new int[160 * 160 * 2];
+ private int[] _penBuffer = new int[PEN_BUFFER_WIDTH * PEN_BUFFER_HEIGHT];
///
/// The output framebuffer
@@ -90,13 +93,11 @@ namespace BizHawk.Emulation.Cores.Consoles.SuperVision
WritePixels(data, framePolarity);
// setup for next frame
- _vPos = 0;
- _hPos = 0;
+ ResetPosition();
}
else if (lineLatch)
{
// end of scanline
- //
_hPos = 0;
_vPos++;
}
@@ -115,13 +116,27 @@ namespace BizHawk.Emulation.Cores.Consoles.SuperVision
{
for (int i = 0; i < 4; i++)
{
- _frameBuffer[(_vPos * 160 * 2) + (_hPos + framePolarity)] = (data >> i) & 0x01;
+ if (_hPos < PEN_BUFFER_WIDTH && _vPos < PEN_BUFFER_HEIGHT)
+ {
+ _penBuffer[(_vPos * 160 * 2) + (_hPos + framePolarity)] = (data >> i) & 0x01;
+ }
+ else
+ {
+ // bits out of bounds of the LCD screen
+ // data is discarded
+ }
+
_hPos += 2;
}
}
+ public void SetRates(int num, int dom)
+ {
+ VsyncNumerator = num;
+ VsyncDenominator = dom;
+ }
- public int VirtualWidth => BufferWidth;
+ public int VirtualWidth => (int)(BufferWidth * 1.25);
public int VirtualHeight => BufferHeight;
public int BufferWidth => 160;
public int BufferHeight => 160;
@@ -144,6 +159,7 @@ namespace BizHawk.Emulation.Cores.Consoles.SuperVision
{
ser.BeginSection("LCD");
ser.Sync(nameof(_frameBuffer), ref _frameBuffer, false);
+ ser.Sync(nameof(_penBuffer), ref _penBuffer, false);
ser.Sync(nameof(_hPos), ref _hPos);
ser.Sync(nameof(_vPos), ref _vPos);
ser.Sync(nameof(DisplayEnable), ref DisplayEnable);
diff --git a/src/BizHawk.Emulation.Cores/Consoles/Watara/SuperVision/Memory.cs b/src/BizHawk.Emulation.Cores/Consoles/Watara/SuperVision/Memory.cs
index 5312730841..29a0305b4d 100644
--- a/src/BizHawk.Emulation.Cores/Consoles/Watara/SuperVision/Memory.cs
+++ b/src/BizHawk.Emulation.Cores/Consoles/Watara/SuperVision/Memory.cs
@@ -11,9 +11,7 @@ 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
@@ -30,53 +28,54 @@ namespace BizHawk.Emulation.Cores.Consoles.SuperVision
_cpuMemoryAccess = true;
byte result = 0xFF;
- if (address < 0x2000)
+ var divider = address / 0x2000;
+
+ switch (divider)
{
- // RAM
- return WRAM[address];
- }
+ case 0:
+ // WRAM
+ result = WRAM[address];
+ break;
- if (address < 0x4000)
- {
- // port access
- return ReadHardware(address);
- }
+ case 1:
+ // IO address space
+ break;
- if (address < 0x6000)
- {
- // VRAM
- return VRAM[address - 0x4000];
- }
+ case 2:
+ // VRAM
+ result = VRAM[address - 0x4000];
+ break;
- if (address < 0x8000)
- {
- // nothing here
- }
+ case 3:
+ // nothing here
+ break;
- if (address < 0xC000)
- {
- // cartridge rom banking
- // 0x8000 - 0xBFFF is selectable using the 3 bits from the SystemControl register
- switch (BankSelect)
- {
- // first 16k
- case 0:
- return _cartridge.ReadByte((ushort)(address % 0x2000));
+ case 4:
+ // cartridge rom banking
+ // 0x8000 - 0xBFFF is selectable using the 3 bits from the SystemControl register
+ switch (BankSelect)
+ {
+ // first 16k
+ case 0:
+ result = _cartridge.ReadByte((ushort) (address % 0x2000));
+ break;
- // second 16k
- case 1:
- return _cartridge.ReadByte((ushort)((address % 0x2000) + 0x2000));
+ // second 16k
+ case 1:
+ result = _cartridge.ReadByte((ushort) ((address % 0x2000) + 0x2000));
+ break;
- // third 16k
- case 2:
- return _cartridge.ReadByte((ushort)((address % 0x2000) + 0x4000));
- }
- }
+ // third 16k
+ case 2:
+ result = _cartridge.ReadByte((ushort) ((address % 0x2000) + 0x4000));
+ break;
+ }
+ break;
- if (address < 0xFFFF)
- {
- // fixed to the last 16K in the cart address space
- return _cartridge.ReadByte((ushort)((address % 0x2000) + 0x6000));
+ case 5:
+ // fixed to the last 16K in the cart address space
+ result = _cartridge.ReadByte(address);
+ break;
}
return result;
diff --git a/src/BizHawk.Emulation.Cores/Consoles/Watara/SuperVision/SuperVision.IEmulator.cs b/src/BizHawk.Emulation.Cores/Consoles/Watara/SuperVision/SuperVision.IEmulator.cs
index a737ec1260..878f31293e 100644
--- a/src/BizHawk.Emulation.Cores/Consoles/Watara/SuperVision/SuperVision.IEmulator.cs
+++ b/src/BizHawk.Emulation.Cores/Consoles/Watara/SuperVision/SuperVision.IEmulator.cs
@@ -18,7 +18,11 @@ namespace BizHawk.Emulation.Cores.Consoles.SuperVision
private int _frameClock;
private int _frame;
- public int FrameClock => _frameClock;
+ public int FrameClock
+ {
+ get => _frameClock;
+ set => _frameClock = value;
+ }
public int Frame => _frame;
private void CalcClock()
@@ -31,6 +35,10 @@ namespace BizHawk.Emulation.Cores.Consoles.SuperVision
2; // fields per frame
double refreshRate = _cpuClocksPerSecond / _cpuClocksPerFrame; // 50.8130081300813
+
+ _asic.Screen.SetRates(
+ (int) _cpuClocksPerSecond,
+ (int) _cpuClocksPerFrame);
}
public bool FrameAdvance(IController controller, bool render, bool renderSound)
diff --git a/src/BizHawk.Emulation.Cores/Consoles/Watara/SuperVision/SuperVision.cs b/src/BizHawk.Emulation.Cores/Consoles/Watara/SuperVision/SuperVision.cs
index 72bcc81e5f..20858c5a26 100644
--- a/src/BizHawk.Emulation.Cores/Consoles/Watara/SuperVision/SuperVision.cs
+++ b/src/BizHawk.Emulation.Cores/Consoles/Watara/SuperVision/SuperVision.cs
@@ -28,6 +28,9 @@ namespace BizHawk.Emulation.Cores.Consoles.SuperVision
_tracer = new TraceBuffer(_cpu.TraceHeader);
_asic = new ASIC(this, _syncSettings);
+ CalcClock();
+
+ ser.Register(_asic.Screen);
ser.Register(_tracer);
ser.Register(_cpu);
ser.Register(new StateSerializer(SyncState));