diff --git a/BizHawk.Emulation.Cores/Computers/MSX/MSX.cs b/BizHawk.Emulation.Cores/Computers/MSX/MSX.cs index f747c6afec..e35a1a3af1 100644 --- a/BizHawk.Emulation.Cores/Computers/MSX/MSX.cs +++ b/BizHawk.Emulation.Cores/Computers/MSX/MSX.cs @@ -27,9 +27,17 @@ namespace BizHawk.Emulation.Cores.Computers.MSX Array.Resize(ref RomData, ((RomData.Length / BankSize) + 1) * BankSize); } + // we want all ROMS to be multiples of 64K for easy memory mapping later + if (RomData.Length != 0x10000) + { + Array.Resize(ref RomData, 0x10000); + } + Bios = comm.CoreFileProvider.GetFirmware("MSX", "bios", true, "BIOS Not Found, Cannot Load"); Basic = comm.CoreFileProvider.GetFirmware("MSX", "basic", true, "BIOS Not Found, Cannot Load"); + Basic = new byte[0x4000]; + MSX_Pntr = LibMSX.MSX_create(); LibMSX.MSX_load_bios(MSX_Pntr, Bios, Basic); diff --git a/libHawk/MSXHawk/MSXHawk/Core.h b/libHawk/MSXHawk/MSXHawk/Core.h index 7eebad0aa9..013b7d49af 100644 --- a/libHawk/MSXHawk/MSXHawk/Core.h +++ b/libHawk/MSXHawk/MSXHawk/Core.h @@ -19,7 +19,7 @@ namespace MSXHawk MemMap.vdp_pntr = &vdp; MemMap.psg_pntr = &psg; cpu.mem_ctrl = &MemMap; - vdp.INT_FLAG = &cpu.FlagI; + vdp.IRQ_PTR = &cpu.FlagI; vdp.SHOW_BG = vdp.SHOW_SPRITES = true; psg.Clock_Divider = 16; }; @@ -63,8 +63,7 @@ namespace MSXHawk { vdp.InterruptPendingSet(true); - if (vdp.EnableInterrupts()) - cpu.NonMaskableInterruptset(true); + if (vdp.EnableInterrupts()) { cpu.FlagI = true; } } for (uint32_t j = 0; j < vdp.IPeriod; j++) diff --git a/libHawk/MSXHawk/MSXHawk/MSXHawk.cpp b/libHawk/MSXHawk/MSXHawk/MSXHawk.cpp index e7432bbcfa..7bb21252a5 100644 --- a/libHawk/MSXHawk/MSXHawk/MSXHawk.cpp +++ b/libHawk/MSXHawk/MSXHawk/MSXHawk.cpp @@ -41,9 +41,10 @@ MSXHawk_EXPORT void MSX_load(MSXCore* p, uint8_t* rom_1, uint32_t size_1, uint32 } // advance a frame -MSXHawk_EXPORT void MSX_frame_advance(MSXCore* p, uint8_t ctrl1, uint8_t ctrl2, bool render, bool sound) +MSXHawk_EXPORT bool MSX_frame_advance(MSXCore* p, uint8_t ctrl1, uint8_t ctrl2, bool render, bool sound) { p->FrameAdvance(ctrl1, ctrl2, render, sound); + return p->vdp.EnableInterrupts(); } // send video data to external video provider diff --git a/libHawk/MSXHawk/MSXHawk/Memory.cpp b/libHawk/MSXHawk/MSXHawk/Memory.cpp index ae8af780dd..8e1c17169e 100644 --- a/libHawk/MSXHawk/MSXHawk/Memory.cpp +++ b/libHawk/MSXHawk/MSXHawk/Memory.cpp @@ -16,12 +16,21 @@ namespace MSXHawk { port &= 0xFF; - if (port >= 0xA0 && port < 0xC0) // VDP data/control ports + if (port == 0x98) // VDP { - if ((port & 1) == 0) - return vdp_pntr->ReadData(); - else - return vdp_pntr->ReadVdpStatus(); + return vdp_pntr->ReadData(); + } + else if (port == 0x99) // VDP + { + return vdp_pntr->ReadVdpStatus(); + } + else if (port == 0xA1) + { + // not readable + } + else if (port == 0xA8) + { + return PortA8; } return 0xFF; @@ -80,7 +89,7 @@ namespace MSXHawk { for (uint32_t i = 0; i < 16; i++) { - cpu_pntr->MemoryMap[i] = &ram[0xC000 + (0x400 * i)]; + cpu_pntr->MemoryMap[i] = &ram[(0x400 * i)]; cpu_pntr->MemoryMapMask[i] = 0xFF; } } @@ -97,7 +106,7 @@ namespace MSXHawk { for (uint32_t i = 0; i < 16; i++) { - cpu_pntr->MemoryMap[i + 16] = &rom_1[04000 + (0x400 * i)]; + cpu_pntr->MemoryMap[i + 16] = &rom_1[0x4000 + (0x400 * i)]; cpu_pntr->MemoryMapMask[i + 16] = 0; } } @@ -105,7 +114,7 @@ namespace MSXHawk { for (uint32_t i = 0; i < 16; i++) { - cpu_pntr->MemoryMap[i + 16] = &rom_2[04000 + (0x400 * i)]; + cpu_pntr->MemoryMap[i + 16] = &rom_2[0x4000 + (0x400 * i)]; cpu_pntr->MemoryMapMask[i + 16] = 0; } } @@ -113,7 +122,7 @@ namespace MSXHawk { for (uint32_t i = 0; i < 16; i++) { - cpu_pntr->MemoryMap[i + 16] = &ram[0x8000 + (0x400 * i)]; + cpu_pntr->MemoryMap[i + 16] = &ram[0x4000 + (0x400 * i)]; cpu_pntr->MemoryMapMask[i + 16] = 0xFF; } } @@ -146,7 +155,7 @@ namespace MSXHawk { for (uint32_t i = 0; i < 16; i++) { - cpu_pntr->MemoryMap[i + 32] = &ram[0x4000 + (0x400 * i)]; + cpu_pntr->MemoryMap[i + 32] = &ram[0x8000 + (0x400 * i)]; cpu_pntr->MemoryMapMask[i + 32] = 0xFF; } } @@ -179,7 +188,7 @@ namespace MSXHawk { for (uint32_t i = 0; i < 16; i++) { - cpu_pntr->MemoryMap[i + 48] = &ram[(0x400 * i)]; + cpu_pntr->MemoryMap[i + 48] = &ram[0xC000 + (0x400 * i)]; cpu_pntr->MemoryMapMask[i + 48] = 0xFF; } } diff --git a/libHawk/MSXHawk/MSXHawk/Memory.h b/libHawk/MSXHawk/MSXHawk/Memory.h index f296ff7f23..b34ac72e66 100644 --- a/libHawk/MSXHawk/MSXHawk/Memory.h +++ b/libHawk/MSXHawk/MSXHawk/Memory.h @@ -137,7 +137,7 @@ namespace MSXHawk *saver = reg_FFFE; saver++; *saver = reg_FFFF; saver++; - std::memcpy(saver, &ram, 0x2000); saver += 0x2000; + std::memcpy(saver, &ram, 0x10000); saver += 0x10000; std::memcpy(saver, &cart_ram, 0x8000); saver += 0x8000; return saver; diff --git a/libHawk/MSXHawk/MSXHawk/TMS9918A.h b/libHawk/MSXHawk/MSXHawk/TMS9918A.h index 33c9d033e1..c07c2676af 100644 --- a/libHawk/MSXHawk/MSXHawk/TMS9918A.h +++ b/libHawk/MSXHawk/MSXHawk/TMS9918A.h @@ -17,8 +17,8 @@ namespace MSXHawk } - // external pointers to CPU - bool* INT_FLAG = nullptr; + bool* IRQ_PTR = nullptr; + // external flags to display background or sprites bool SHOW_BG, SHOW_SPRITES; bool SpriteLimit; @@ -35,8 +35,7 @@ namespace MSXHawk uint8_t Registers[8] = {}; uint8_t VRAM[0x4000]; //16kb video RAM - int32_t ScanLine; - uint32_t IPeriod = 228; + int32_t ScanLine; uint32_t VdpAddress; uint32_t TmsMode; uint32_t ColorTableBase; @@ -47,7 +46,9 @@ namespace MSXHawk uint32_t FrameBuffer[192 * 256] = {}; + // constants after load, not stated uint32_t BackgroundColor = 0; + uint32_t IPeriod = 228; uint32_t PaletteTMS9918[16] = { @@ -134,7 +135,7 @@ namespace MSXHawk break; case 1: // Mode Control Register 2 CheckVideoMode(); - INT_FLAG[0] = (EnableInterrupts() && InterruptPendingGet()); + IRQ_PTR[0] = (EnableInterrupts() && InterruptPendingGet()); break; case 2: // Name Table Base Address TmsPatternNameTableBase = (Registers[2] << 10) & 0x3C00; @@ -159,7 +160,7 @@ namespace MSXHawk VdpWaitingForLatchByte = true; uint8_t returnValue = StatusByte; StatusByte &= 0x1F; - INT_FLAG[0] = false; + IRQ_PTR[0] = false; return returnValue; } @@ -508,13 +509,83 @@ namespace MSXHawk uint8_t* SaveState(uint8_t* saver) { + *saver = (uint8_t)(VdpWaitingForLatchInt ? 1 : 0); saver++; + *saver = (uint8_t)(VdpWaitingForLatchByte ? 1 : 0); saver++; + *saver = (uint8_t)(VIntPending ? 1 : 0); saver++; + *saver = (uint8_t)(HIntPending ? 1 : 0); saver++; + + *saver = StatusByte; saver++; + *saver = VdpLatch; saver++; + *saver = VdpBuffer; saver++; + + std::memcpy(saver, &Registers, 8); saver += 8; + std::memcpy(saver, &VRAM, 0x4000); saver += 0x4000; + + *saver = (uint8_t)(ScanLine & 0xFF); saver++; *saver = (uint8_t)((ScanLine >> 8) & 0xFF); saver++; + *saver = (uint8_t)((ScanLine >> 16) & 0xFF); saver++; *saver = (uint8_t)((ScanLine >> 24) & 0xFF); saver++; + + *saver = (uint8_t)(VdpAddress & 0xFF); saver++; *saver = (uint8_t)((VdpAddress >> 8) & 0xFF); saver++; + *saver = (uint8_t)((VdpAddress >> 16) & 0xFF); saver++; *saver = (uint8_t)((VdpAddress >> 24) & 0xFF); saver++; + + *saver = (uint8_t)(TmsMode & 0xFF); saver++; *saver = (uint8_t)((TmsMode >> 8) & 0xFF); saver++; + *saver = (uint8_t)((TmsMode >> 16) & 0xFF); saver++; *saver = (uint8_t)((TmsMode >> 24) & 0xFF); saver++; + + *saver = (uint8_t)(ColorTableBase & 0xFF); saver++; *saver = (uint8_t)((ColorTableBase >> 8) & 0xFF); saver++; + *saver = (uint8_t)((ColorTableBase >> 16) & 0xFF); saver++; *saver = (uint8_t)((ColorTableBase >> 24) & 0xFF); saver++; + + *saver = (uint8_t)(PatternGeneratorBase & 0xFF); saver++; *saver = (uint8_t)((PatternGeneratorBase >> 8) & 0xFF); saver++; + *saver = (uint8_t)((PatternGeneratorBase >> 16) & 0xFF); saver++; *saver = (uint8_t)((PatternGeneratorBase >> 24) & 0xFF); saver++; + + *saver = (uint8_t)(SpritePatternGeneratorBase & 0xFF); saver++; *saver = (uint8_t)((SpritePatternGeneratorBase >> 8) & 0xFF); saver++; + *saver = (uint8_t)((SpritePatternGeneratorBase >> 16) & 0xFF); saver++; *saver = (uint8_t)((SpritePatternGeneratorBase >> 24) & 0xFF); saver++; + + *saver = (uint8_t)(TmsPatternNameTableBase & 0xFF); saver++; *saver = (uint8_t)((TmsPatternNameTableBase >> 8) & 0xFF); saver++; + *saver = (uint8_t)((TmsPatternNameTableBase >> 16) & 0xFF); saver++; *saver = (uint8_t)((TmsPatternNameTableBase >> 24) & 0xFF); saver++; + + *saver = (uint8_t)(TmsSpriteAttributeBase & 0xFF); saver++; *saver = (uint8_t)((TmsSpriteAttributeBase >> 8) & 0xFF); saver++; + *saver = (uint8_t)((TmsSpriteAttributeBase >> 16) & 0xFF); saver++; *saver = (uint8_t)((TmsSpriteAttributeBase >> 24) & 0xFF); saver++; return saver; } uint8_t* LoadState(uint8_t* loader) { + VdpWaitingForLatchInt = *loader == 1; loader++; + VdpWaitingForLatchByte = *loader == 1; loader++; + VIntPending = *loader == 1; loader++; + HIntPending = *loader == 1; loader++; + StatusByte = *loader; loader++; + VdpLatch = *loader; loader++; + VdpBuffer = *loader; loader++; + + std::memcpy(&Registers, loader, 8); loader += 8; + std::memcpy(&VRAM, loader, 0x4000); loader += 0x4000; + + ScanLine = *loader; loader++; ScanLine |= (*loader << 8); loader++; + ScanLine |= (*loader << 16); loader++; ScanLine |= (*loader << 24); loader++; + + VdpAddress = *loader; loader++; VdpAddress |= (*loader << 8); loader++; + VdpAddress |= (*loader << 16); loader++; VdpAddress |= (*loader << 24); loader++; + + TmsMode = *loader; loader++; TmsMode |= (*loader << 8); loader++; + TmsMode |= (*loader << 16); loader++; TmsMode |= (*loader << 24); loader++; + + ColorTableBase = *loader; loader++; ColorTableBase |= (*loader << 8); loader++; + ColorTableBase |= (*loader << 16); loader++; ColorTableBase |= (*loader << 24); loader++; + + PatternGeneratorBase = *loader; loader++; PatternGeneratorBase |= (*loader << 8); loader++; + PatternGeneratorBase |= (*loader << 16); loader++; PatternGeneratorBase |= (*loader << 24); loader++; + + SpritePatternGeneratorBase = *loader; loader++; SpritePatternGeneratorBase |= (*loader << 8); loader++; + SpritePatternGeneratorBase |= (*loader << 16); loader++; SpritePatternGeneratorBase |= (*loader << 24); loader++; + + TmsPatternNameTableBase = *loader; loader++; TmsPatternNameTableBase |= (*loader << 8); loader++; + TmsPatternNameTableBase |= (*loader << 16); loader++; TmsPatternNameTableBase |= (*loader << 24); loader++; + + TmsSpriteAttributeBase = *loader; loader++; TmsSpriteAttributeBase |= (*loader << 8); loader++; + TmsSpriteAttributeBase |= (*loader << 16); loader++; TmsSpriteAttributeBase |= (*loader << 24); loader++; + return loader; } diff --git a/libHawk/MSXHawk/MSXHawk/Z80A.h b/libHawk/MSXHawk/MSXHawk/Z80A.h index 5e3b0e142b..c0dd3b2310 100644 --- a/libHawk/MSXHawk/MSXHawk/Z80A.h +++ b/libHawk/MSXHawk/MSXHawk/Z80A.h @@ -474,7 +474,7 @@ namespace MSXHawk inline bool NonMaskableInterruptget() { return nonMaskableInterrupt; }; inline void NonMaskableInterruptset(bool value) { - if (value && !nonMaskableInterrupt) nonMaskableInterruptPending = true; + if (value && !nonMaskableInterrupt) { nonMaskableInterruptPending = true; } nonMaskableInterrupt = value; }