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) public void LoadGameRom(string path)
{ {
const int bankSize = 0x4000;
this.gameRomBanks.Clear(); 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; var banks = size / bankSize;
for (var bank = 1; bank < banks; ++bank) for (var bank = 1; bank < banks; ++bank)
{ {
this.gameRomBanks.Add(new Rom()); var bankedROM = new Rom();
_ = this.gameRomBanks[bank].Load(path, 0, bankSize * bank, bankSize); _ = bankedROM.Load(path, 0, bankSize * bank, bankSize);
this.gameRomBanks.Add(bankedROM);
} }
this.ValidateCartridgeType(); this.ValidateCartridgeType();
@ -99,7 +104,7 @@ namespace LR35902
public void RunRasterLines() 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.IO.ResetLY();
this.RunRasterLines(DisplayCharacteristics.RasterHeight); this.RunRasterLines(DisplayCharacteristics.RasterHeight);
} }
@ -406,7 +411,7 @@ namespace LR35902
} }
else 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) for (var bit = 0; bit < 8; ++bit)
{ {
var mask = 1 << bit; var mask = Chip.Bit(bit);
var bitLow = (planeLow & mask) != 0 ? 1 : 0; var bitLow = (planeLow & mask) != 0 ? 1 : 0;
var bitHigh = (planeHigh & mask) != 0 ? 0b10 : 0; var bitHigh = (planeHigh & mask) != 0 ? 0b10 : 0;
returned[7 - bit] = bitHigh | bitLow; var index = 7 - bit;
returned[index] = bitHigh | bitLow;
} }
return returned; return returned;

View File

@ -24,14 +24,14 @@ namespace LR35902
if (this.scanLine < DisplayCharacteristics.RasterHeight) if (this.scanLine < DisplayCharacteristics.RasterHeight)
{ {
this.control = this.bus.IO.Peek(IoRegisters.LCDC); 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(); this.RenderBackground();
} }
if ((this.control & (byte)LcdcControls.ObjectEnable) != 0) if ((this.control & (byte)LcdcControls.OBJ_EN) != 0)
{ {
this.RenderObjects(); this.RenderObjects();
} }
@ -63,9 +63,9 @@ namespace LR35902
{ {
var palette = this.CreatePalette(IoRegisters.BGP); var palette = this.CreatePalette(IoRegisters.BGP);
var window = (this.control & (byte)LcdcControls.WindowEnable) != 0; var window = (this.control & (byte)LcdcControls.WIN_EN) != 0;
var bgArea = (this.control & (byte)LcdcControls.BackgroundCodeAreaSelection) != 0 ? 0x1c00 : 0x1800; var bgArea = (this.control & (byte)LcdcControls.BG_MAP) != 0 ? 0x1c00 : 0x1800;
var bgCharacters = (this.control & (byte)LcdcControls.BackgroundCharacterDataSelection) != 0 ? 0 : 0x800; var bgCharacters = (this.control & (byte)LcdcControls.TILE_SEL) != 0 ? 0 : 0x800;
var wx = this.bus.IO.Peek(IoRegisters.WX); var wx = this.bus.IO.Peek(IoRegisters.WX);
var wy = this.bus.IO.Peek(IoRegisters.WY); var wy = this.bus.IO.Peek(IoRegisters.WY);
@ -88,13 +88,16 @@ namespace LR35902
{ {
var character = this.vram.Peek((ushort)address++); var character = this.vram.Peek((ushort)address++);
var definition = new CharacterDefinition(this.vram, (ushort)(bgCharacters + (16 * character))); 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() 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][]; var palettes = new int[2][];
palettes[0] = this.CreatePalette(IoRegisters.OBP0); palettes[0] = this.CreatePalette(IoRegisters.OBP0);
@ -120,12 +123,45 @@ namespace LR35902
var flipX = current.FlipX; var flipX = current.FlipX;
var flipY = current.FlipY; 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 width = 8;
const int flipMaskX = width - 1; const int flipMaskX = width - 1;

View File

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

View File

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

View File

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

View File

@ -38,6 +38,6 @@ namespace LR35902
public bool FlipX => (this.Flags & (byte)Bits.Bit5) != 0; 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;
} }
} }