Some video work

This commit is contained in:
Asnivor 2024-11-07 16:23:44 +00:00
parent 58473484a0
commit 0474de9605
2 changed files with 104 additions and 46 deletions

View File

@ -42,24 +42,11 @@ namespace BizHawk.Emulation.Cores.Consoles.SuperVision
public const int R_SYSTEM_CONTROL = 0x26;
public const int R_IRQ_STATUS = 0x27;
/// <summary>
/// Scanline length in cpu clocks
/// </summary>
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
/// <summary>
/// Y offset modifier used with Y_Scroll to determine the VRAM pointer
/// </summary>
public int Y_OFFSET => _regs[R_LCD_X_SIZE] > 0xC0 ? 0x30 : 0x60;
/// <summary>
/// Number of scanlines in a field
/// </summary>
public int LINE_HEIGHT => _regs[R_LCD_Y_SIZE];
private SuperVision _sv;
private byte[] _regs = new byte[0x2000];
public byte[] Regs => _regs;
@ -86,7 +73,7 @@ namespace BizHawk.Emulation.Cores.Consoles.SuperVision
private int _seqCounter;
private int _byteCounter;
private int _lineCounter;
private int _field;
private bool _field;
private ushort _vramByteBuffer;
private int _vramPointer;
private int _vramStartAddress;
@ -134,13 +121,80 @@ namespace BizHawk.Emulation.Cores.Consoles.SuperVision
AudioClock(ticks);
// video
for (int i = 0; i < lcdCycles; i++)
{
_byteCounter++;
if (_byteCounter * 4 <= (_regs[R_LCD_X_SIZE] & 0b1111_1100))
{
// still sending pixel data to the LCD
// 4 pixles (bits) per byte read
_vramPointer = (ushort) (_vramStartAddress + (_regs[R_X_SCROLL] >> 2) + _byteCounter - 1);
//_vramPointer = (ushort)(_vramPointer + _byteCounter - 1);
// read a byte of data from VRAM
byte data = _sv.ReadVRAM((ushort)_vramPointer);
// 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);
// structure the correct bits based on the current field
byte lData = !_field
? (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));
Screen.PixelClock(lData);
}
else if (_byteCounter * 4 > (_regs[R_LCD_X_SIZE] & 0b1111_1100))
{
// end of scanline
_lineCounter++;
_byteCounter = 0;
if (_lineCounter < _regs[R_LCD_Y_SIZE])
{
// still within the frame
// pulse line latch
Screen.LineLatch();
// vstart is updated every scanline
// it is incremented based on the X_Size register
int inc = _regs[R_LCD_X_SIZE] > 0xC3 ? 0x60 : 0x30;
_vramStartAddress = (_vramStartAddress + inc) & 0x1FFFF;
if (_vramStartAddress == 0x1FE0)
_vramStartAddress = 0;
}
else
{
// end of field
_lineCounter = 0;
// pulse the frame latch
Screen.FrameLatch();
// new field
_field = !_field;
Screen.FramePolarity = _field;
// setup memory pointer for beginning of field
_vramStartAddress = (_regs[R_Y_SCROLL] * 0x30) & 0x1FFF;
if (_vramStartAddress == 0x1FE0)
{
_vramStartAddress = 0;
}
// setup for the next scanline
_vramPointer = _vramStartAddress + (_regs[R_X_SCROLL] >> 2);
}
}
}
_sv.FrameClock += ticks;
}
/*
/// <summary>
/// Runs a single clock cycle of the ASIC
/// </summary>
@ -256,7 +310,7 @@ namespace BizHawk.Emulation.Cores.Consoles.SuperVision
_sv.FrameClock++;
}
*/
/// <summary>
/// Interrupt management

View File

@ -89,47 +89,50 @@ namespace BizHawk.Emulation.Cores.Consoles.SuperVision
// 9 - Power Control
/// <summary>
/// It takes 6 cycles for each write to the LCD screen (so 1 pixelclock == 6 cpu cycles)
/// Pulsed at the end of a field
/// Clears the column and row shift registers
/// </summary>
public void PixelClock(byte data, int framePolarity = 0, bool lineLatch = false, bool frameLatch = false)
{
// Each scanline is composed of 246 clocks.
// There are 40 pixel writes to the LCD, and 1 latch write, for a total of 41 writes.
// Each write period lasts 6 clock cycles, so 41*6 = 246 cycles
if (frameLatch)
{
// end of field
// write last pixel
if (DisplayEnable)
WritePixels(data, framePolarity);
public void FrameLatch() => ResetPosition();
// setup for next frame
ResetPosition();
}
else if (lineLatch)
{
// end of scanline
_hPos = 0;
_vPos++;
}
else
{
if (DisplayEnable)
WritePixels(data, framePolarity);
}
/// <summary>
/// When pulsed, data from the column shift register latched into the current LCD glass column
/// The row shift register is then clocked
/// </summary>
public void LineLatch()
{
_vPos++;
_hPos = 0;
}
/// <summary>
/// This outputs 4 pixels at a time - we only use the first 4 bits of the data
/// 2BPP, bit0 is written in the first field, bit1 in the second
/// The frame polarity/bright control signal is toggled every field
/// This inverts all the driver signals
/// It also darkens the display a bit so you can get a true 2 bits per pixel
/// The polarity toggling is done to prevent destruction of the LCD display glass via electrolytic plating action
/// </summary>
private void WritePixels(byte data, int framePolarity)
public bool FramePolarity
{
get { return _framePolarity; }
set { _framePolarity = value; }
}
private bool _framePolarity;
/// <summary>
/// Bit offset when writing to the framebuffer
/// </summary>
private int _polarityOffset => FramePolarity ? 1 : 0;
/// <summary>
/// It takes 6 cycles for each write to the LCD screen (so 1 pixelclock == 6 cpu cycles)
/// </summary>
public void PixelClock(byte data)
{
for (int i = 0; i < 4; i++)
{
if (_hPos < PEN_BUFFER_WIDTH && _vPos < PEN_BUFFER_HEIGHT)
{
_penBuffer[(_vPos * 160 * 2) + (_hPos + framePolarity)] = (data >> i) & 0x01;
_penBuffer[(_vPos * 160 * 2) + (_hPos + _polarityOffset)] = (data >> i) & 0x01;
}
else
{
@ -147,7 +150,7 @@ namespace BizHawk.Emulation.Cores.Consoles.SuperVision
VsyncDenominator = dom;
}
public int VirtualWidth => (int)(BufferWidth * 1.25);
public int VirtualWidth => BufferWidth;
public int VirtualHeight => BufferHeight;
public int BufferWidth => 160;
public int BufferHeight => 160;
@ -174,6 +177,7 @@ namespace BizHawk.Emulation.Cores.Consoles.SuperVision
ser.Sync(nameof(_hPos), ref _hPos);
ser.Sync(nameof(_vPos), ref _vPos);
ser.Sync(nameof(DisplayEnable), ref DisplayEnable);
ser.Sync(nameof(FramePolarity), ref _framePolarity);
ser.EndSection();
}
}