Synchonise with unmanaged GB implementation

This commit is contained in:
Adrian Conlon 2024-10-14 11:04:51 +01:00
parent fa13852e53
commit 4b4181e12d
7 changed files with 83 additions and 36 deletions

View File

@ -83,15 +83,20 @@ namespace LR35902
public void LoadGameRom(string path)
{
const int bankSize = 0x4000;
this.gameRomBanks.Clear();
this.gameRomBanks.Add(new Rom());
var size = this.gameRomBanks[0].Load(path, 0, 0, bankSize);
const int bankSize = 0x4000;
var rom = new Rom();
var size = rom.Load(path, 0, 0, bankSize);
this.gameRomBanks.Add(rom);
var banks = size / bankSize;
for (var bank = 1; bank < banks; ++bank)
{
this.gameRomBanks.Add(new Rom());
_ = this.gameRomBanks[bank].Load(path, 0, bankSize * bank, bankSize);
var bankedROM = new Rom();
_ = bankedROM.Load(path, 0, bankSize * bank, bankSize);
this.gameRomBanks.Add(bankedROM);
}
this.ValidateCartridgeType();
@ -99,7 +104,7 @@ namespace LR35902
public void RunRasterLines()
{
this.enabledLCD = (this.IO.Peek(IoRegisters.LCDC) & (byte)LcdcControls.LcdEnable) != 0;
this.enabledLCD = (this.IO.Peek(IoRegisters.LCDC) & (byte)LcdcControls.LCD_EN) != 0;
this.IO.ResetLY();
this.RunRasterLines(DisplayCharacteristics.RasterHeight);
}
@ -406,7 +411,7 @@ namespace LR35902
}
else
{
this.allowed -= this.CPU.Run(this.allowed);
this.allowed -= this.CPU.Run(CyclesPerLine);
}
}
}

View File

@ -22,12 +22,13 @@ namespace LR35902
for (var bit = 0; bit < 8; ++bit)
{
var mask = 1 << bit;
var mask = Chip.Bit(bit);
var bitLow = (planeLow & mask) != 0 ? 1 : 0;
var bitHigh = (planeHigh & mask) != 0 ? 0b10 : 0;
returned[7 - bit] = bitHigh | bitLow;
var index = 7 - bit;
returned[index] = bitHigh | bitLow;
}
return returned;

View File

@ -24,14 +24,14 @@ namespace LR35902
if (this.scanLine < DisplayCharacteristics.RasterHeight)
{
this.control = this.bus.IO.Peek(IoRegisters.LCDC);
if ((this.control & (byte)LcdcControls.LcdEnable) != 0)
if ((this.control & (byte)LcdcControls.LCD_EN) != 0)
{
if ((this.control & (byte)LcdcControls.DisplayBackground) != 0)
if ((this.control & (byte)LcdcControls.BG_EN) != 0)
{
this.RenderBackground();
}
if ((this.control & (byte)LcdcControls.ObjectEnable) != 0)
if ((this.control & (byte)LcdcControls.OBJ_EN) != 0)
{
this.RenderObjects();
}
@ -63,9 +63,9 @@ namespace LR35902
{
var palette = this.CreatePalette(IoRegisters.BGP);
var window = (this.control & (byte)LcdcControls.WindowEnable) != 0;
var bgArea = (this.control & (byte)LcdcControls.BackgroundCodeAreaSelection) != 0 ? 0x1c00 : 0x1800;
var bgCharacters = (this.control & (byte)LcdcControls.BackgroundCharacterDataSelection) != 0 ? 0 : 0x800;
var window = (this.control & (byte)LcdcControls.WIN_EN) != 0;
var bgArea = (this.control & (byte)LcdcControls.BG_MAP) != 0 ? 0x1c00 : 0x1800;
var bgCharacters = (this.control & (byte)LcdcControls.TILE_SEL) != 0 ? 0 : 0x800;
var wx = this.bus.IO.Peek(IoRegisters.WX);
var wy = this.bus.IO.Peek(IoRegisters.WY);
@ -88,13 +88,16 @@ namespace LR35902
{
var character = this.vram.Peek((ushort)address++);
var definition = new CharacterDefinition(this.vram, (ushort)(bgCharacters + (16 * character)));
this.RenderTile(8, (column * 8) + offsetX, (row * 8) + offsetY, false, false, false, palette, definition);
this.RenderBackgroundTile(
(column * 8) + offsetX, (row * 8) + offsetY,
palette,
definition);
}
}
private void RenderObjects()
{
var objBlockHeight = (this.control & (byte)LcdcControls.ObjectBlockCompositionSelection) != 0 ? 16 : 8;
var objBlockHeight = (this.control & (byte)LcdcControls.OBJ_SIZE) != 0 ? 16 : 8;
var palettes = new int[2][];
palettes[0] = this.CreatePalette(IoRegisters.OBP0);
@ -120,12 +123,45 @@ namespace LR35902
var flipX = current.FlipX;
var flipY = current.FlipY;
this.RenderTile(objBlockHeight, drawX, drawY, flipX, flipY, true, palette, definition);
this.RenderSpriteTile(
objBlockHeight,
drawX, drawY,
flipX, flipY,
palette,
definition);
}
}
}
private void RenderTile(int height, int drawX, int drawY, bool flipX, bool flipY, bool allowTransparencies, int[] palette, CharacterDefinition definition)
private void RenderSpriteTile(
int height,
int drawX, int drawY,
bool flipX, bool flipY,
int[] palette,
CharacterDefinition definition) => this.RenderTile(
height,
drawX, drawY,
flipX, flipY, true,
palette,
definition);
private void RenderBackgroundTile(
int drawX, int drawY,
int[] palette,
CharacterDefinition definition) => this.RenderTile(
8,
drawX, drawY,
false, false, false,
palette,
definition);
private void RenderTile(
int height,
int drawX, int drawY,
bool flipX, bool flipY,
bool allowTransparencies,
int[] palette,
CharacterDefinition definition)
{
const int width = 8;
const int flipMaskX = width - 1;

View File

@ -122,7 +122,7 @@ namespace LR35902
public void Reset()
{
this.Poke(NR52, 0xf1);
this.Poke(LCDC, (byte)(LcdcControls.DisplayBackground | LcdcControls.BackgroundCharacterDataSelection | LcdcControls.LcdEnable));
this.Poke(LCDC, (byte)(LcdcControls.BG_EN | LcdcControls.TILE_SEL | LcdcControls.LCD_EN));
this.divCounter.Word = 0xabcc;
this.timerCounter = 0;
}
@ -168,7 +168,7 @@ namespace LR35902
public void UpdateLcdStatusMode(LcdStatusMode mode)
{
var current = this.Peek(STAT) & unchecked((byte)~Mask.Two);
var current = this.Peek(STAT) & ~(byte)Mask.Two;
this.Poke(STAT, (byte)(current | (int)mode));
this.OnDisplayStatusModeUpdated(mode);
}
@ -273,6 +273,12 @@ namespace LR35902
private void ApplyMask(ushort address, byte masking) => this.Poke(address, (byte)(this.Peek(address) | ~masking));
private void ApplyMask(ushort address, int masking) => this.ApplyMask(address, (byte)masking);
private void ApplyMask(ushort address, Bits masking) => this.ApplyMask(address, (byte)masking);
private void ApplyMask(ushort address, Mask masking) => this.ApplyMask(address, (byte)masking);
private void TriggerKeypadInterrupt() => this.TriggerInterrupt(Interrupts.KeypadPressed);
private void Bus_WrittenByte(object? sender, EventArgs e)
@ -335,7 +341,7 @@ namespace LR35902
private void Bus_ReadingByte(object? sender, EventArgs e)
{
var address = this.bus.Address.Word;
var io = address >= BASE && address < 0xff80;
var io = address is >= BASE and < 0xff80;
if (io)
{
var port = (ushort)(address - BASE);
@ -361,7 +367,7 @@ namespace LR35902
case SB:
break;
case SC:
this.ApplyMask(port, (byte)(Bits.Bit7 | Bits.Bit0));
this.ApplyMask(port, Bits.Bit7 | Bits.Bit0);
break;
// Timer control
@ -370,19 +376,19 @@ namespace LR35902
case TMA:
break;
case TAC:
this.ApplyMask(port, (byte)Mask.Three);
this.ApplyMask(port, Mask.Three);
break;
// Interrupt Flags
case IF:
this.ApplyMask(port, (byte)Mask.Five);
this.ApplyMask(port, Mask.Five);
break;
// LCD Display Registers
case LCDC:
break;
case STAT:
this.ApplyMask(port, (byte)Mask.Seven);
this.ApplyMask(port, Mask.Seven);
break;
case SCY:
case SCX:

View File

@ -120,7 +120,6 @@ namespace LR35902
MachineTicked?.Invoke(this, EventArgs.Empty);
this.bus.IO.IncrementTimers();
this.bus.IO.TransferDma();
}
private void TickMachine(int extra)

View File

@ -10,13 +10,13 @@ namespace LR35902
public enum LcdcControls
{
None = 0,
DisplayBackground = Bits.Bit0,
ObjectEnable = Bits.Bit1,
ObjectBlockCompositionSelection = Bits.Bit2,
BackgroundCodeAreaSelection = Bits.Bit3,
BackgroundCharacterDataSelection = Bits.Bit4,
WindowEnable = Bits.Bit5,
WindowCodeAreaSelection = Bits.Bit6,
LcdEnable = Bits.Bit7,
BG_EN = Bits.Bit0,
OBJ_EN = Bits.Bit1,
OBJ_SIZE = Bits.Bit2,
BG_MAP = Bits.Bit3,
TILE_SEL = Bits.Bit4,
WIN_EN = Bits.Bit5,
WIN_MAP = Bits.Bit6,
LCD_EN = Bits.Bit7,
}
}

View File

@ -38,6 +38,6 @@ namespace LR35902
public bool FlipX => (this.Flags & (byte)Bits.Bit5) != 0;
public int Palette => (this.Flags & (byte)Bits.Bit4) >> 3; // TODO: Check this!
public int Palette => (this.Flags & (byte)Bits.Bit4) >> 4;
}
}