MSXHawk: properly load roms and memory map
This commit is contained in:
parent
8fed99456a
commit
5521f0cf19
|
@ -5,7 +5,7 @@ using BizHawk.Emulation.Common;
|
|||
namespace BizHawk.Emulation.Cores.Computers.MSX
|
||||
{
|
||||
/// <summary>
|
||||
/// static bindings into libMSX.dll
|
||||
/// static bindings into MSXHAWK.dll
|
||||
/// </summary>
|
||||
public static class LibMSX
|
||||
{
|
||||
|
@ -16,5 +16,16 @@ namespace BizHawk.Emulation.Cores.Computers.MSX
|
|||
/// <param name="core">opaque state pointer</param>
|
||||
[DllImport("MSXHAWK.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void MSX_destroy(IntPtr core);
|
||||
|
||||
/// <summary>
|
||||
/// Load ROM image.
|
||||
/// </summary>
|
||||
/// <param name="core">opaque state pointer</param>
|
||||
/// <param name="romdata">the rom data, can be disposed of once this function returns</param>
|
||||
/// <param name="length">length of romdata in bytes</param>
|
||||
/// <param name="mapper">Mapper number to load core with</param>
|
||||
/// <returns>0 on success, negative value on failure.</returns>
|
||||
[DllImport("MSXHAWK.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern int MSX_load(IntPtr core, byte[] romdata, uint length, int mapper);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ namespace BizHawk.Emulation.Cores.Computers.MSX
|
|||
}
|
||||
|
||||
MSX_Pntr = LibMSX.MSX_create();
|
||||
LibMSX.MSX_load(MSX_Pntr, RomData, (uint)RomData.Length, 0);
|
||||
|
||||
blip_L.SetRates(3579545, 44100);
|
||||
blip_R.SetRates(3579545, 44100);
|
||||
|
|
|
@ -16,31 +16,136 @@ namespace MSXHawk
|
|||
public:
|
||||
MSXCore()
|
||||
{
|
||||
cpu.HW_Read = &HardwareRead;
|
||||
cpu.HW_Write = &HardwareWrite;
|
||||
};
|
||||
|
||||
VDP vdp;
|
||||
Z80A cpu;
|
||||
SN76489sms psg;
|
||||
|
||||
static void Load_ROM(uint8_t* ext_rom, uint32_t ext_rom_size, uint32_t ext_rom_mapper)
|
||||
{
|
||||
rom = ext_rom;
|
||||
rom_size = ext_rom_size / 0x4000;
|
||||
rom_mapper = ext_rom_mapper;
|
||||
|
||||
unsigned char* rom;
|
||||
unsigned int rom_size;
|
||||
unsigned char ram[0x2000];
|
||||
// default memory map setup
|
||||
reg_FFFC = 0;
|
||||
reg_FFFD = 0;
|
||||
reg_FFFE = 0;
|
||||
reg_FFFF = 0;
|
||||
remap_ROM_0();
|
||||
remap_ROM_1();
|
||||
remap_ROM_2();
|
||||
remap_RAM();
|
||||
}
|
||||
|
||||
static void HardwareWrite(uint8_t value)
|
||||
static VDP vdp;
|
||||
static Z80A cpu;
|
||||
static SN76489sms psg;
|
||||
|
||||
static uint8_t* rom;
|
||||
static uint32_t rom_size;
|
||||
static uint32_t rom_mapper;
|
||||
static uint8_t ram[0x2000];
|
||||
|
||||
static uint8_t cart_ram[0x8000];
|
||||
|
||||
static uint8_t HardwareRead(uint32_t value)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void HardwareWrite(uint32_t addr, uint8_t value)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// memory map
|
||||
unsigned char* Memory_Map[8];
|
||||
|
||||
void Load_ROM(unsigned char* ext_rom, unsigned int ext_rom_size)
|
||||
static void MemoryWrite(uint32_t addr, uint8_t value)
|
||||
{
|
||||
rom = ext_rom;
|
||||
rom_size = ext_rom_size;
|
||||
switch (addr)
|
||||
{
|
||||
case 0xFFFC:
|
||||
reg_FFFC = value;
|
||||
remap_ROM_2();
|
||||
remap_RAM();
|
||||
break;
|
||||
case 0xFFFD:
|
||||
reg_FFFD = value;
|
||||
remap_ROM_0();
|
||||
break;
|
||||
case 0xFFFE:
|
||||
reg_FFFE = value;
|
||||
remap_ROM_1();
|
||||
break;
|
||||
case 0xFFFF:
|
||||
reg_FFFF = value;
|
||||
remap_ROM_2();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Memory_Map[0] = &rom[0];
|
||||
static uint8_t reg_FFFC, reg_FFFD, reg_FFFE, reg_FFFF;
|
||||
|
||||
static inline void remap_ROM_0()
|
||||
{
|
||||
// 0x0000 - 0x03FF always maps to start of ROM
|
||||
cpu.MemoryMap[0] = &rom[0];
|
||||
cpu.MemoryMapMask[0] = 0;
|
||||
|
||||
for (uint32_t i = 1; i < 16; i++)
|
||||
{
|
||||
cpu.MemoryMap[i] = &rom[(reg_FFFD % rom_size) * 0x4000 + (0x400 * i)];
|
||||
cpu.MemoryMapMask[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void remap_ROM_1()
|
||||
{
|
||||
for (uint32_t i = 0; i < 16; i++)
|
||||
{
|
||||
cpu.MemoryMap[i + 16] = &rom[(reg_FFFE % rom_size) * 0x4000 + (0x400 * i)];
|
||||
cpu.MemoryMapMask[i + 16] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void remap_ROM_2()
|
||||
{
|
||||
if ((reg_FFFC & 0x8) > 0)
|
||||
{
|
||||
for (uint32_t i = 0; i < 16; i++)
|
||||
{
|
||||
cpu.MemoryMap[i + 32] = &cart_ram[((reg_FFFC >> 2) & 0x1) * 0x4000 + (0x400 * i)];
|
||||
cpu.MemoryMapMask[i + 32] = 0xFF;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
cpu.MemoryMap[i + 32] = &rom[(reg_FFFF % rom_size) * 0x4000 + (0x400 * i)];
|
||||
cpu.MemoryMapMask[i + 32] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void remap_RAM()
|
||||
{
|
||||
if ((reg_FFFC & 0x10) > 0)
|
||||
{
|
||||
for (uint32_t i = 0; i < 16; i++)
|
||||
{
|
||||
cpu.MemoryMap[i + 48] = &cart_ram[(0x400 * i)];
|
||||
cpu.MemoryMapMask[i + 48] = 0xFF;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (uint32_t i = 0; i < 8; i++)
|
||||
{
|
||||
cpu.MemoryMap[i + 48] = &ram[(0x400 * i)];
|
||||
cpu.MemoryMap[i + 48 + 8] = &ram[(0x400 * i)];
|
||||
cpu.MemoryMapMask[i + 48] = 0xFF;
|
||||
cpu.MemoryMapMask[i + 48 + 8] = 0xFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -4,10 +4,35 @@
|
|||
#include "MSXHawk.h"
|
||||
#include "Core.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <cstdint>
|
||||
#include <iomanip>
|
||||
#include <string>
|
||||
|
||||
#include "Z80A.h"
|
||||
#include "PSG.h"
|
||||
#include "VDP.h"
|
||||
|
||||
using namespace MSXHawk;
|
||||
|
||||
// initialize static members
|
||||
uint8_t MSXCore::reg_FFFC = 0;
|
||||
uint8_t MSXCore::reg_FFFD = 0;
|
||||
uint8_t MSXCore::reg_FFFE = 0;
|
||||
uint8_t MSXCore::reg_FFFF = 0;
|
||||
|
||||
uint8_t* MSXCore::rom = nullptr;
|
||||
uint32_t MSXCore::rom_size = 0;
|
||||
uint32_t MSXCore::rom_mapper = 0;
|
||||
uint8_t MSXCore::ram[0x2000] = {};
|
||||
uint8_t MSXCore::cart_ram[0x8000] = {};
|
||||
|
||||
Z80A MSXCore::cpu;
|
||||
SN76489sms MSXCore::psg;
|
||||
VDP MSXCore::vdp;
|
||||
|
||||
// Create pointer to a core instance
|
||||
MSXHAWK_EXPORT MSXCore* MSX_create()
|
||||
MSXHAWK_EXPORT MSXCore* MSX_create()
|
||||
{
|
||||
return new MSXCore();
|
||||
}
|
||||
|
@ -18,3 +43,9 @@ MSXHAWK_EXPORT void MSX_destroy(MSXCore* p)
|
|||
std::free(p);
|
||||
}
|
||||
|
||||
// load a rom into the core
|
||||
MSXHAWK_EXPORT void MSX_load(MSXCore* p, uint8_t* rom, unsigned int size, int mapper)
|
||||
{
|
||||
p->Load_ROM(rom, size, mapper);
|
||||
}
|
||||
|
||||
|
|
|
@ -12,8 +12,8 @@ namespace MSXHawk
|
|||
class SN76489sms
|
||||
{
|
||||
public:
|
||||
int current_sample_L;
|
||||
int current_sample_R;
|
||||
uint32_t current_sample_L;
|
||||
uint32_t current_sample_R;
|
||||
|
||||
SN76489sms()
|
||||
{
|
||||
|
@ -23,23 +23,23 @@ namespace MSXHawk
|
|||
uint8_t Chan_vol[4];
|
||||
uint16_t Chan_tone[4];
|
||||
|
||||
int chan_sel;
|
||||
uint32_t chan_sel;
|
||||
bool vol_tone;
|
||||
bool noise_type;
|
||||
int noise_rate;
|
||||
uint32_t noise_rate;
|
||||
bool noise_bit;
|
||||
|
||||
bool A_L, B_L, C_L, noise_L;
|
||||
bool A_R, B_R, C_R, noise_R;
|
||||
|
||||
int psg_clock;
|
||||
uint32_t psg_clock;
|
||||
|
||||
int clock_A, clock_B, clock_C;
|
||||
uint32_t clock_A, clock_B, clock_C;
|
||||
|
||||
bool A_up, B_up, C_up;
|
||||
|
||||
int noise_clock;
|
||||
int noise;
|
||||
uint32_t noise_clock;
|
||||
uint32_t noise;
|
||||
|
||||
uint8_t stereo_panning;
|
||||
const uint8_t LogScale[16] = { 255, 203, 161, 128, 102, 86, 64, 51, 40, 32, 26, 20, 16, 13, 10, 0 };
|
||||
|
|
|
@ -31,40 +31,40 @@ namespace MSXHawk
|
|||
|
||||
}
|
||||
|
||||
const int Command_VramRead = 0x00;
|
||||
const int Command_VramWrite = 0x40;
|
||||
const int Command_RegisterWrite = 0x80;
|
||||
const int Command_CramWrite = 0xC0;
|
||||
const uint32_t Command_VramRead = 0x00;
|
||||
const uint32_t Command_VramWrite = 0x40;
|
||||
const uint32_t Command_RegisterWrite = 0x80;
|
||||
const uint32_t Command_CramWrite = 0xC0;
|
||||
|
||||
const int MODE_SMS = 1;
|
||||
const int MODE_GG = 2;
|
||||
const uint32_t MODE_SMS = 1;
|
||||
const uint32_t MODE_GG = 2;
|
||||
|
||||
const int DISP_TYPE_NTSC = 1;
|
||||
const int DISP_TYPE_PAL = 2;
|
||||
const uint32_t DISP_TYPE_NTSC = 1;
|
||||
const uint32_t DISP_TYPE_PAL = 2;
|
||||
|
||||
bool VdpWaitingForLatchuint8_t = true;
|
||||
uint8_t VdpLatch;
|
||||
uint8_t VdpBuffer;
|
||||
uint16_t VdpAddress;
|
||||
uint8_t VdpCommand;
|
||||
int TmsMode = 4;
|
||||
uint8_t HCounter = 0x90;
|
||||
uint32_t TmsMode = 4;
|
||||
|
||||
bool VIntPending;
|
||||
bool HIntPending;
|
||||
int lineIntLinesRemaining;
|
||||
uint32_t lineIntLinesRemaining;
|
||||
|
||||
int mode;
|
||||
int DisplayType;
|
||||
uint32_t mode;
|
||||
uint32_t DisplayType;
|
||||
|
||||
bool SpriteLimit;
|
||||
int IPeriod = 228;
|
||||
|
||||
int FrameHeight = 192;
|
||||
int ScanLine;
|
||||
uint8_t HCounter = 0x90;
|
||||
int FrameBuffer[256 * 244];
|
||||
int GameGearFrameBuffer[160 * 144];
|
||||
int OverscanFrameBuffer[1];
|
||||
|
||||
int32_t IPeriod = 228;
|
||||
int32_t FrameHeight = 192;
|
||||
int32_t FrameBuffer[256 * 244];
|
||||
int32_t GameGearFrameBuffer[160 * 144];
|
||||
int32_t OverscanFrameBuffer[1];
|
||||
int32_t ScanLine;
|
||||
|
||||
inline bool Mode1Bit() { return (Registers[1] & 16) > 0; }
|
||||
inline bool Mode2Bit() {return (Registers[0] & 2) > 0; }
|
||||
|
@ -79,19 +79,19 @@ namespace MSXHawk
|
|||
inline bool EnableLargeSprites() { return (Registers[1] & 2) > 0; }
|
||||
inline bool EnableFrameInterrupts() { return (Registers[1] & 32) > 0; }
|
||||
inline bool DisplayOn() { return (Registers[1] & 64) > 0; }
|
||||
int SpriteAttributeTableBase() { return ((Registers[5] >> 1) << 8) & 0x3FFF; }
|
||||
int SpriteTileBase() { return (Registers[6] & 4) > 0 ? 256 : 0; }
|
||||
uint32_t SpriteAttributeTableBase() { return ((Registers[5] >> 1) << 8) & 0x3FFF; }
|
||||
uint32_t SpriteTileBase() { return (Registers[6] & 4) > 0 ? 256 : 0; }
|
||||
uint8_t BackdropColor() { return (uint8_t)(16 + (Registers[7] & 15)); }
|
||||
|
||||
int NameTableBase;
|
||||
int ColorTableBase;
|
||||
int PatternGeneratorBase;
|
||||
int SpritePatternGeneratorBase;
|
||||
int TmsPatternNameTableBase;
|
||||
int TmsSpriteAttributeBase;
|
||||
uint32_t NameTableBase;
|
||||
uint32_t ColorTableBase;
|
||||
uint32_t PatternGeneratorBase;
|
||||
uint32_t SpritePatternGeneratorBase;
|
||||
uint32_t TmsPatternNameTableBase;
|
||||
uint32_t TmsSpriteAttributeBase;
|
||||
|
||||
// preprocessed state assist stuff.
|
||||
int Palette[32];
|
||||
uint32_t Palette[32];
|
||||
uint8_t PatternBuffer[0x8000];
|
||||
|
||||
uint8_t ScanlinePriorityBuffer[256];
|
||||
|
@ -192,7 +192,7 @@ namespace MSXHawk
|
|||
if (VdpCommand == Command_CramWrite)
|
||||
{
|
||||
// Write Palette / CRAM
|
||||
int mask = mode == MODE_SMS ? 0x1F : 0x3F;
|
||||
uint32_t mask = mode == MODE_SMS ? 0x1F : 0x3F;
|
||||
CRAM[VdpAddress & mask] = value;
|
||||
UpdatePrecomputedPalette();
|
||||
}
|
||||
|
@ -209,7 +209,7 @@ namespace MSXHawk
|
|||
{
|
||||
if (mode == MODE_SMS)
|
||||
{
|
||||
for (int i = 0; i < 32; i++)
|
||||
for (uint32_t i = 0; i < 32; i++)
|
||||
{
|
||||
uint8_t value = CRAM[i];
|
||||
uint8_t r = SMSPalXlatTable[(value & 0x03)];
|
||||
|
@ -220,7 +220,7 @@ namespace MSXHawk
|
|||
}
|
||||
else
|
||||
{ // GameGear
|
||||
for (int i = 0; i < 32; i++)
|
||||
for (uint32_t i = 0; i < 32; i++)
|
||||
{
|
||||
uint16_t value = (uint16_t)((CRAM[(i * 2) + 1] << 8) | CRAM[(i * 2) + 0]);
|
||||
uint8_t r = GGPalXlatTable[(value & 0x000F)];
|
||||
|
@ -231,12 +231,12 @@ namespace MSXHawk
|
|||
}
|
||||
}
|
||||
|
||||
int ARGB(uint8_t red, uint8_t green, uint8_t blue)
|
||||
uint32_t ARGB(uint8_t red, uint8_t green, uint8_t blue)
|
||||
{
|
||||
return (int)((red << 0x10) | (green << 8) | blue | (0xFF << 0x18));
|
||||
return (uint32_t)((red << 0x10) | (green << 8) | blue | (0xFF << 0x18));
|
||||
}
|
||||
|
||||
int CalcNameTableBase()
|
||||
uint32_t CalcNameTableBase()
|
||||
{
|
||||
if (FrameHeight == 192)
|
||||
return 1024 * (Registers[2] & 0x0E);
|
||||
|
@ -294,7 +294,7 @@ namespace MSXHawk
|
|||
}
|
||||
}
|
||||
|
||||
void WriteRegister(int reg, uint8_t data)
|
||||
void WriteRegister(uint32_t reg, uint8_t data)
|
||||
{
|
||||
Registers[reg] = data;
|
||||
|
||||
|
@ -336,7 +336,7 @@ namespace MSXHawk
|
|||
void UpdatePatternBuffer(uint16_t address, uint8_t value)
|
||||
{
|
||||
// writing one uint8_t affects 8 pixels due to stupid planar storage.
|
||||
for (int i = 0; i < 8; i++)
|
||||
for (uint32_t i = 0; i < 8; i++)
|
||||
{
|
||||
uint8_t colorBit = pow2[address % 4];
|
||||
uint8_t sourceBit = pow2[7 - i];
|
||||
|
@ -429,7 +429,7 @@ namespace MSXHawk
|
|||
|
||||
if (ser.IsReader)
|
||||
{
|
||||
for (int i = 0; i < Registers.Length; i++)
|
||||
for (uint32_t i = 0; i < Registers.Length; i++)
|
||||
WriteRegister(i, Registers[i]);
|
||||
for (uint16_t i = 0; i < VRAM.Length; i++)
|
||||
UpdatePatternBuffer(i, VRAM[i]);
|
||||
|
@ -438,17 +438,17 @@ namespace MSXHawk
|
|||
}
|
||||
*/
|
||||
|
||||
int VirtualWidth = 160;
|
||||
uint32_t VirtualWidth = 160;
|
||||
|
||||
int VirtualHeight = 160; // GameGear
|
||||
uint32_t VirtualHeight = 160; // GameGear
|
||||
|
||||
int BufferHeight = 144; // GameGear
|
||||
uint32_t BufferHeight = 144; // GameGear
|
||||
|
||||
int BackgroundColor() { return Palette[BackdropColor()]; }
|
||||
uint32_t BackgroundColor() { return Palette[BackdropColor()]; }
|
||||
|
||||
int VsyncNumerator = 60;
|
||||
uint32_t VsyncNumerator = 60;
|
||||
|
||||
int VsyncDenominator = 1;
|
||||
uint32_t VsyncDenominator = 1;
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Mode4
|
||||
|
@ -460,20 +460,20 @@ namespace MSXHawk
|
|||
|
||||
if (DisplayOn() == false)
|
||||
{
|
||||
for (int x = 0; x < 256; x++)
|
||||
for (uint32_t x = 0; x < 256; x++)
|
||||
FrameBuffer[(ScanLine * 256) + x] = Palette[BackdropColor()];
|
||||
return;
|
||||
}
|
||||
|
||||
// Clear the priority buffer for this scanline
|
||||
for (int i = 0; i < 256; i++)
|
||||
for (uint32_t i = 0; i < 256; i++)
|
||||
{
|
||||
ScanlinePriorityBuffer[i] = 0;
|
||||
}
|
||||
|
||||
int mapBase = NameTableBase;
|
||||
uint32_t mapBase = NameTableBase;
|
||||
|
||||
int vertOffset = ScanLine + Registers[9];
|
||||
uint32_t vertOffset = ScanLine + Registers[9];
|
||||
if (FrameHeight == 192)
|
||||
{
|
||||
if (vertOffset >= 224)
|
||||
|
@ -486,9 +486,9 @@ namespace MSXHawk
|
|||
}
|
||||
uint8_t horzOffset = (HorizScrollLock() && ScanLine < 16) ? (uint8_t)0 : Registers[8];
|
||||
|
||||
int yTile = vertOffset / 8;
|
||||
uint32_t yTile = vertOffset / 8;
|
||||
|
||||
for (int xTile = 0; xTile < 32; xTile++)
|
||||
for (uint32_t xTile = 0; xTile < 32; xTile++)
|
||||
{
|
||||
if (xTile == 24 && VerticalScrollLock())
|
||||
{
|
||||
|
@ -497,15 +497,15 @@ namespace MSXHawk
|
|||
}
|
||||
|
||||
uint8_t PaletteBase = 0;
|
||||
int tileInfo = VRAM[mapBase + ((yTile * 32) + xTile) * 2] | (VRAM[mapBase + (((yTile * 32) + xTile) * 2) + 1] << 8);
|
||||
int tileNo = tileInfo & 0x01FF;
|
||||
uint32_t tileInfo = VRAM[mapBase + ((yTile * 32) + xTile) * 2] | (VRAM[mapBase + (((yTile * 32) + xTile) * 2) + 1] << 8);
|
||||
uint32_t tileNo = tileInfo & 0x01FF;
|
||||
if ((tileInfo & 0x800) != 0)
|
||||
PaletteBase = 16;
|
||||
bool Priority = (tileInfo & 0x1000) != 0;
|
||||
bool VFlip = (tileInfo & 0x400) != 0;
|
||||
bool HFlip = (tileInfo & 0x200) != 0;
|
||||
|
||||
int yOfs = vertOffset & 7;
|
||||
uint32_t yOfs = vertOffset & 7;
|
||||
if (VFlip)
|
||||
yOfs = 7 - yOfs;
|
||||
|
||||
|
@ -523,7 +523,7 @@ namespace MSXHawk
|
|||
if (Priority)
|
||||
{
|
||||
horzOffset -= 8;
|
||||
for (int k = 0; k < 8; k++)
|
||||
for (uint32_t k = 0; k < 8; k++)
|
||||
{
|
||||
if (PatternBuffer[(tileNo * 64) + (yOfs * 8) + k] != 0)
|
||||
ScanlinePriorityBuffer[horzOffset] = 1;
|
||||
|
@ -545,7 +545,7 @@ namespace MSXHawk
|
|||
if (Priority)
|
||||
{
|
||||
horzOffset -= 8;
|
||||
for (int k = 7; k >= 0; k--)
|
||||
for (int32_t k = 7; k >= 0; k--)
|
||||
{
|
||||
if (PatternBuffer[(tileNo * 64) + (yOfs * 8) + k] != 0)
|
||||
ScanlinePriorityBuffer[horzOffset] = 1;
|
||||
|
@ -573,24 +573,24 @@ namespace MSXHawk
|
|||
overflowHappens = false;
|
||||
}
|
||||
|
||||
int SpriteBase = SpriteAttributeTableBase();
|
||||
int SpriteHeight = EnableLargeSprites() ? 16 : 8;
|
||||
int32_t SpriteBase = SpriteAttributeTableBase();
|
||||
int32_t SpriteHeight = EnableLargeSprites() ? 16 : 8;
|
||||
|
||||
// Clear the sprite collision buffer for this scanline
|
||||
for (int i = 0; i < 256; i++)
|
||||
for (int32_t i = 0; i < 256; i++)
|
||||
{
|
||||
SpriteCollisionBuffer[i] = 0;
|
||||
}
|
||||
|
||||
// Loop through these sprites and render the current scanline
|
||||
int SpritesDrawnThisScanline = 0;
|
||||
for (int i = 0; i < 64; i++)
|
||||
int32_t SpritesDrawnThisScanline = 0;
|
||||
for (int32_t i = 0; i < 64; i++)
|
||||
{
|
||||
int x = VRAM[SpriteBase + 0x80 + (i * 2)];
|
||||
int32_t x = VRAM[SpriteBase + 0x80 + (i * 2)];
|
||||
if (ShiftSpritesLeft8Pixels())
|
||||
x -= 8;
|
||||
|
||||
int y = VRAM[SpriteBase + i] + 1;
|
||||
int32_t y = VRAM[SpriteBase + i] + 1;
|
||||
if (y == 209 && FrameHeight == 192)
|
||||
break; // 208 is special terminator sprite (in 192-line mode)
|
||||
if (y >= (EnableLargeSprites() ? 240 : 248))
|
||||
|
@ -608,14 +608,14 @@ namespace MSXHawk
|
|||
renderHappens = false; // should be able to break/return, but to ensure this has no effect on sync we keep processing and disable rendering
|
||||
}
|
||||
|
||||
int tileNo = VRAM[SpriteBase + 0x80 + (i * 2) + 1];
|
||||
int32_t tileNo = VRAM[SpriteBase + 0x80 + (i * 2) + 1];
|
||||
if (EnableLargeSprites())
|
||||
tileNo &= 0xFE;
|
||||
tileNo += SpriteTileBase();
|
||||
|
||||
int ys = ScanLine - y;
|
||||
int32_t ys = ScanLine - y;
|
||||
|
||||
for (int xs = 0; xs < 8 && x + xs < 256; xs++)
|
||||
for (int32_t xs = 0; xs < 8 && x + xs < 256; xs++)
|
||||
{
|
||||
uint8_t color = PatternBuffer[(tileNo * 64) + (ys * 8) + xs];
|
||||
if (color != 0 && x + xs >= 0)
|
||||
|
@ -653,24 +653,24 @@ namespace MSXHawk
|
|||
overflowHappens = false;
|
||||
}
|
||||
|
||||
int SpriteBase = SpriteAttributeTableBase();
|
||||
int SpriteHeight = EnableLargeSprites() ? 16 : 8;
|
||||
int32_t SpriteBase = SpriteAttributeTableBase();
|
||||
int32_t SpriteHeight = EnableLargeSprites() ? 16 : 8;
|
||||
|
||||
// Clear the sprite collision buffer for this scanline
|
||||
for (int i = 0; i < 256; i++)
|
||||
for (uint32_t i = 0; i < 256; i++)
|
||||
{
|
||||
SpriteCollisionBuffer[i] = 0;
|
||||
}
|
||||
|
||||
// Loop through these sprites and render the current scanline
|
||||
int SpritesDrawnThisScanline = 0;
|
||||
for (int i = 0; i < 64; i++)
|
||||
int32_t SpritesDrawnThisScanline = 0;
|
||||
for (int32_t i = 0; i < 64; i++)
|
||||
{
|
||||
int x = VRAM[SpriteBase + 0x80 + (i * 2)];
|
||||
int32_t x = VRAM[SpriteBase + 0x80 + (i * 2)];
|
||||
if (ShiftSpritesLeft8Pixels())
|
||||
x -= 8;
|
||||
|
||||
int y = VRAM[SpriteBase + i] + 1;
|
||||
int32_t y = VRAM[SpriteBase + i] + 1;
|
||||
if (y == 209 && FrameHeight == 192)
|
||||
break; // terminator sprite
|
||||
if (y >= (EnableLargeSprites() ? 240 : 248))
|
||||
|
@ -688,14 +688,14 @@ namespace MSXHawk
|
|||
renderHappens = false; // should be able to break/return, but to ensure this has no effect on sync we keep processing and disable rendering
|
||||
}
|
||||
|
||||
int tileNo = VRAM[SpriteBase + 0x80 + (i * 2) + 1];
|
||||
int32_t tileNo = VRAM[SpriteBase + 0x80 + (i * 2) + 1];
|
||||
if (EnableLargeSprites())
|
||||
tileNo &= 0xFE;
|
||||
tileNo += SpriteTileBase();
|
||||
|
||||
int ys = ScanLine - y;
|
||||
int32_t ys = ScanLine - y;
|
||||
|
||||
for (int xs = 0; xs < 16 && x + xs < 256; xs++)
|
||||
for (int32_t xs = 0; xs < 16 && x + xs < 256; xs++)
|
||||
{
|
||||
uint8_t color = PatternBuffer[(tileNo * 64) + ((ys / 2) * 8) + (xs / 2)];
|
||||
if (color != 0 && x + xs >= 0)
|
||||
|
@ -722,16 +722,16 @@ namespace MSXHawk
|
|||
if (!LeftBlanking() || ScanLine >= FrameHeight || !render)
|
||||
return;
|
||||
|
||||
int ofs = ScanLine * 256;
|
||||
for (int x = 0; x < 8; x++)
|
||||
int32_t ofs = ScanLine * 256;
|
||||
for (int32_t x = 0; x < 8; x++)
|
||||
FrameBuffer[ofs++] = Palette[BackdropColor()];
|
||||
}
|
||||
|
||||
int OverscanFrameWidth, OverscanFrameHeight;
|
||||
int overscanTop;
|
||||
int overscanBottom;
|
||||
int overscanLeft;
|
||||
int overscanRight;
|
||||
int32_t OverscanFrameWidth, OverscanFrameHeight;
|
||||
int32_t overscanTop;
|
||||
int32_t overscanBottom;
|
||||
int32_t overscanLeft;
|
||||
int32_t overscanRight;
|
||||
|
||||
/*
|
||||
void ProcessOverscan()
|
||||
|
@ -762,28 +762,28 @@ namespace MSXHawk
|
|||
}
|
||||
|
||||
// Top overscan
|
||||
for (int y = 0; y < overscanTop; y++)
|
||||
for (int x = 0; x < OverscanFrameWidth; x++)
|
||||
for (uint32_t y = 0; y < overscanTop; y++)
|
||||
for (uint32_t x = 0; x < OverscanFrameWidth; x++)
|
||||
OverscanFrameBuffer[(y * OverscanFrameWidth) + x] = BackgroundColor();
|
||||
|
||||
// Bottom overscan
|
||||
for (int y = overscanTop + 192; y < OverscanFrameHeight; y++)
|
||||
for (int x = 0; x < OverscanFrameWidth; x++)
|
||||
for (uint32_t y = overscanTop + 192; y < OverscanFrameHeight; y++)
|
||||
for (uint32_t x = 0; x < OverscanFrameWidth; x++)
|
||||
OverscanFrameBuffer[(y * OverscanFrameWidth) + x] = BackgroundColor();
|
||||
|
||||
// Left overscan
|
||||
for (int y = overscanTop; y < overscanTop + 192; y++)
|
||||
for (int x = 0; x < overscanLeft; x++)
|
||||
for (uint32_t y = overscanTop; y < overscanTop + 192; y++)
|
||||
for (uint32_t x = 0; x < overscanLeft; x++)
|
||||
OverscanFrameBuffer[(y * OverscanFrameWidth) + x] = BackgroundColor();
|
||||
|
||||
// Right overscan
|
||||
for (int y = overscanTop; y < overscanTop + 192; y++)
|
||||
for (int x = overscanLeft + 256; x < OverscanFrameWidth; x++)
|
||||
for (uint32_t y = overscanTop; y < overscanTop + 192; y++)
|
||||
for (uint32_t x = overscanLeft + 256; x < OverscanFrameWidth; x++)
|
||||
OverscanFrameBuffer[(y * OverscanFrameWidth) + x] = BackgroundColor();
|
||||
|
||||
// Active display area
|
||||
for (int y = 0; y < 192; y++)
|
||||
for (int x = 0; x < 256; x++)
|
||||
for (uint32_t y = 0; y < 192; y++)
|
||||
for (uint32_t x = 0; x < 256; x++)
|
||||
OverscanFrameBuffer[((y + overscanTop) * OverscanFrameWidth) + overscanLeft + x] = FrameBuffer[y * 256 + x];
|
||||
}
|
||||
*/
|
||||
|
@ -792,54 +792,54 @@ namespace MSXHawk
|
|||
// Handles GG clipping or highlighting
|
||||
void ProcessGGScreen()
|
||||
{
|
||||
int yStart = (FrameHeight - 144) / 2;
|
||||
for (int y = 0; y < 144; y++)
|
||||
for (int x = 0; x < 160; x++)
|
||||
uint32_t yStart = (FrameHeight - 144) / 2;
|
||||
for (uint32_t y = 0; y < 144; y++)
|
||||
for (uint32_t x = 0; x < 160; x++)
|
||||
GameGearFrameBuffer[(y * 160) + x] = FrameBuffer[((y + yStart) * 256) + x + 48];
|
||||
/*
|
||||
if (Sms.Settings.HighlightActiveDisplayRegion && Sms.Settings.ShowClippedRegions)
|
||||
{
|
||||
// Top 24 scanlines
|
||||
for (int y = 0; y < 24; y++)
|
||||
for (uint32_t y = 0; y < 24; y++)
|
||||
{
|
||||
for (int x = 0; x < 256; x++)
|
||||
for (uint32_t x = 0; x < 256; x++)
|
||||
{
|
||||
int frameOffset = (y * 256) + x;
|
||||
int p = (FrameBuffer[frameOffset] >> 1) & 0x7F7F7F7F;
|
||||
FrameBuffer[frameOffset] = (int)(p | 0x80000000);
|
||||
uint32_t frameOffset = (y * 256) + x;
|
||||
uint32_t p = (FrameBuffer[frameOffset] >> 1) & 0x7F7F7F7F;
|
||||
FrameBuffer[frameOffset] = (uint32_t)(p | 0x80000000);
|
||||
}
|
||||
}
|
||||
|
||||
// Bottom 24 scanlines
|
||||
for (int y = 168; y < 192; y++)
|
||||
for (uint32_t y = 168; y < 192; y++)
|
||||
{
|
||||
for (int x = 0; x < 256; x++)
|
||||
for (uint32_t x = 0; x < 256; x++)
|
||||
{
|
||||
int frameOffset = (y * 256) + x;
|
||||
int p = (FrameBuffer[frameOffset] >> 1) & 0x7F7F7F7F;
|
||||
FrameBuffer[frameOffset] = (int)(p | 0x80000000);
|
||||
uint32_t frameOffset = (y * 256) + x;
|
||||
uint32_t p = (FrameBuffer[frameOffset] >> 1) & 0x7F7F7F7F;
|
||||
FrameBuffer[frameOffset] = (uint32_t)(p | 0x80000000);
|
||||
}
|
||||
}
|
||||
|
||||
// Left 48 pixels
|
||||
for (int y = 24; y < 168; y++)
|
||||
for (uint32_t y = 24; y < 168; y++)
|
||||
{
|
||||
for (int x = 0; x < 48; x++)
|
||||
for (uint32_t x = 0; x < 48; x++)
|
||||
{
|
||||
int frameOffset = (y * 256) + x;
|
||||
int p = (FrameBuffer[frameOffset] >> 1) & 0x7F7F7F7F;
|
||||
FrameBuffer[frameOffset] = (int)(p | 0x80000000);
|
||||
uint32_t frameOffset = (y * 256) + x;
|
||||
uint32_t p = (FrameBuffer[frameOffset] >> 1) & 0x7F7F7F7F;
|
||||
FrameBuffer[frameOffset] = (uint32_t)(p | 0x80000000);
|
||||
}
|
||||
}
|
||||
|
||||
// Right 48 pixels
|
||||
for (int y = 24; y < 168; y++)
|
||||
for (uint32_t y = 24; y < 168; y++)
|
||||
{
|
||||
for (int x = 208; x < 256; x++)
|
||||
for (uint32_t x = 208; x < 256; x++)
|
||||
{
|
||||
int frameOffset = (y * 256) + x;
|
||||
int p = (FrameBuffer[frameOffset] >> 1) & 0x7F7F7F7F;
|
||||
FrameBuffer[frameOffset] = (int)(p | 0x80000000);
|
||||
uint32_t frameOffset = (y * 256) + x;
|
||||
uint32_t p = (FrameBuffer[frameOffset] >> 1) & 0x7F7F7F7F;
|
||||
FrameBuffer[frameOffset] = (uint32_t)(p | 0x80000000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -849,7 +849,7 @@ namespace MSXHawk
|
|||
|
||||
#pragma region ModeTMS
|
||||
|
||||
unsigned int PaletteTMS9918[16]
|
||||
uint32_t PaletteTMS9918[16]
|
||||
{
|
||||
0xFF000000,
|
||||
0xFF000000,
|
||||
|
@ -876,28 +876,28 @@ namespace MSXHawk
|
|||
|
||||
if (DisplayOn() == false)
|
||||
{
|
||||
for (int i = ScanLine * 256; i < (ScanLine * 256 + 256); i++)
|
||||
for (int32_t i = ScanLine * 256; i < (ScanLine * 256 + 256); i++)
|
||||
{
|
||||
FrameBuffer[i] = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
int yc = ScanLine / 8;
|
||||
int yofs = ScanLine % 8;
|
||||
int FrameBufferOffset = ScanLine * 256;
|
||||
int PatternNameOffset = TmsPatternNameTableBase + (yc * 32);
|
||||
int ScreenBGColor = PaletteTMS9918[Registers[7] & 0x0F];
|
||||
int32_t yc = ScanLine / 8;
|
||||
int32_t yofs = ScanLine % 8;
|
||||
int32_t FrameBufferOffset = ScanLine * 256;
|
||||
int32_t PatternNameOffset = TmsPatternNameTableBase + (yc * 32);
|
||||
int32_t ScreenBGColor = PaletteTMS9918[Registers[7] & 0x0F];
|
||||
|
||||
for (int xc = 0; xc < 32; xc++)
|
||||
for (int32_t xc = 0; xc < 32; xc++)
|
||||
{
|
||||
int pn = VRAM[PatternNameOffset++];
|
||||
int pv = VRAM[PatternGeneratorBase + (pn * 8) + yofs];
|
||||
int colorEntry = VRAM[ColorTableBase + (pn / 8)];
|
||||
int fgIndex = (colorEntry >> 4) & 0x0F;
|
||||
int bgIndex = colorEntry & 0x0F;
|
||||
int fgColor = fgIndex == 0 ? ScreenBGColor : PaletteTMS9918[fgIndex];
|
||||
int bgColor = bgIndex == 0 ? ScreenBGColor : PaletteTMS9918[bgIndex];
|
||||
int32_t pn = VRAM[PatternNameOffset++];
|
||||
int32_t pv = VRAM[PatternGeneratorBase + (pn * 8) + yofs];
|
||||
int32_t colorEntry = VRAM[ColorTableBase + (pn / 8)];
|
||||
int32_t fgIndex = (colorEntry >> 4) & 0x0F;
|
||||
int32_t bgIndex = colorEntry & 0x0F;
|
||||
int32_t fgColor = fgIndex == 0 ? ScreenBGColor : PaletteTMS9918[fgIndex];
|
||||
int32_t bgColor = bgIndex == 0 ? ScreenBGColor : PaletteTMS9918[bgIndex];
|
||||
|
||||
FrameBuffer[FrameBufferOffset++] = show ? (((pv & 0x80) > 0) ? fgColor : bgColor) : 0;
|
||||
FrameBuffer[FrameBufferOffset++] = show ? (((pv & 0x40) > 0) ? fgColor : bgColor) : 0;
|
||||
|
@ -917,30 +917,30 @@ namespace MSXHawk
|
|||
|
||||
if (DisplayOn() == false)
|
||||
{
|
||||
for (int i = ScanLine * 256; i < (ScanLine * 256 + 256); i++)
|
||||
for (int32_t i = ScanLine * 256; i < (ScanLine * 256 + 256); i++)
|
||||
{
|
||||
FrameBuffer[i] = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
int yrow = ScanLine / 8;
|
||||
int yofs = ScanLine % 8;
|
||||
int FrameBufferOffset = ScanLine * 256;
|
||||
int PatternNameOffset = TmsPatternNameTableBase + (yrow * 32);
|
||||
int PatternGeneratorOffset = (((Registers[4] & 4) << 11) & 0x2000);// +((yrow / 8) * 0x100);
|
||||
int ColorOffset = (ColorTableBase & 0x2000);// +((yrow / 8) * 0x100);
|
||||
int ScreenBGColor = PaletteTMS9918[Registers[7] & 0x0F];
|
||||
int32_t yrow = ScanLine / 8;
|
||||
int32_t yofs = ScanLine % 8;
|
||||
int32_t FrameBufferOffset = ScanLine * 256;
|
||||
int32_t PatternNameOffset = TmsPatternNameTableBase + (yrow * 32);
|
||||
int32_t PatternGeneratorOffset = (((Registers[4] & 4) << 11) & 0x2000);// +((yrow / 8) * 0x100);
|
||||
int32_t ColorOffset = (ColorTableBase & 0x2000);// +((yrow / 8) * 0x100);
|
||||
int32_t ScreenBGColor = PaletteTMS9918[Registers[7] & 0x0F];
|
||||
|
||||
for (int xc = 0; xc < 32; xc++)
|
||||
for (int32_t xc = 0; xc < 32; xc++)
|
||||
{
|
||||
int pn = VRAM[PatternNameOffset++] + ((yrow / 8) * 0x100);
|
||||
int pv = VRAM[PatternGeneratorOffset + (pn * 8) + yofs];
|
||||
int colorEntry = VRAM[ColorOffset + (pn * 8) + yofs];
|
||||
int fgIndex = (colorEntry >> 4) & 0x0F;
|
||||
int bgIndex = colorEntry & 0x0F;
|
||||
int fgColor = fgIndex == 0 ? ScreenBGColor : PaletteTMS9918[fgIndex];
|
||||
int bgColor = bgIndex == 0 ? ScreenBGColor : PaletteTMS9918[bgIndex];
|
||||
int32_t pn = VRAM[PatternNameOffset++] + ((yrow / 8) * 0x100);
|
||||
int32_t pv = VRAM[PatternGeneratorOffset + (pn * 8) + yofs];
|
||||
int32_t colorEntry = VRAM[ColorOffset + (pn * 8) + yofs];
|
||||
int32_t fgIndex = (colorEntry >> 4) & 0x0F;
|
||||
int32_t bgIndex = colorEntry & 0x0F;
|
||||
int32_t fgColor = fgIndex == 0 ? ScreenBGColor : PaletteTMS9918[fgIndex];
|
||||
int32_t bgColor = bgIndex == 0 ? ScreenBGColor : PaletteTMS9918[bgIndex];
|
||||
|
||||
FrameBuffer[FrameBufferOffset++] = show ? (((pv & 0x80) > 0) ? fgColor : bgColor) : 0;
|
||||
FrameBuffer[FrameBufferOffset++] = show ? (((pv & 0x40) > 0) ? fgColor : bgColor) : 0;
|
||||
|
@ -966,29 +966,29 @@ namespace MSXHawk
|
|||
|
||||
void RenderTmsSpritesStandard(bool show)
|
||||
{
|
||||
for (int i = 0; i < 256; i++)
|
||||
for (uint32_t i = 0; i < 256; i++)
|
||||
{
|
||||
ScanlinePriorityBuffer[i] = 0;
|
||||
}
|
||||
for (int i = 0; i < 256; i++)
|
||||
for (uint32_t i = 0; i < 256; i++)
|
||||
{
|
||||
SpriteCollisionBuffer[i] = 0;
|
||||
}
|
||||
|
||||
bool LargeSprites = EnableLargeSprites();
|
||||
|
||||
int SpriteSize = 8;
|
||||
int32_t SpriteSize = 8;
|
||||
if (LargeSprites) SpriteSize *= 2;
|
||||
const int OneCellSize = 8;
|
||||
const int32_t OneCellSize = 8;
|
||||
|
||||
int NumSpritesOnScanline = 0;
|
||||
for (int i = 0; i < 32; i++)
|
||||
int32_t NumSpritesOnScanline = 0;
|
||||
for (int32_t i = 0; i < 32; i++)
|
||||
{
|
||||
int SpriteBase = TmsSpriteAttributeBase + (i * 4);
|
||||
int y = VRAM[SpriteBase++];
|
||||
int x = VRAM[SpriteBase++];
|
||||
int Pattern = VRAM[SpriteBase++];
|
||||
int Color = VRAM[SpriteBase];
|
||||
int32_t SpriteBase = TmsSpriteAttributeBase + (i * 4);
|
||||
int32_t y = VRAM[SpriteBase++];
|
||||
int32_t x = VRAM[SpriteBase++];
|
||||
int32_t Pattern = VRAM[SpriteBase++];
|
||||
int32_t Color = VRAM[SpriteBase];
|
||||
|
||||
if (y == 208) break; // terminator sprite
|
||||
if (y > 224) y -= 256; // sprite Y wrap
|
||||
|
@ -999,13 +999,13 @@ namespace MSXHawk
|
|||
if (++NumSpritesOnScanline == 5)
|
||||
{
|
||||
Statusuint8_t &= 0xE0; // Clear FS0-FS4 bits
|
||||
Statusuint8_t |= (uint8_t)i; // set 5th sprite index
|
||||
Statusuint8_t |= (int8_t)i; // set 5th sprite index
|
||||
Statusuint8_t |= 0x40; // set overflow bit
|
||||
break;
|
||||
}
|
||||
|
||||
if (LargeSprites) Pattern &= 0xFC; // 16x16 sprites forced to 4-uint8_t alignment
|
||||
int SpriteLine = ScanLine - y;
|
||||
int32_t SpriteLine = ScanLine - y;
|
||||
|
||||
// pv contains the VRAM uint8_t holding the pattern data for this character at this scanline.
|
||||
// each uint8_t contains the pattern data for each the 8 pixels on this line.
|
||||
|
@ -1013,7 +1013,7 @@ namespace MSXHawk
|
|||
|
||||
uint8_t pv = VRAM[SpritePatternGeneratorBase + (Pattern * 8) + SpriteLine];
|
||||
|
||||
for (int xp = 0; xp < SpriteSize && x + xp < 256; xp++)
|
||||
for (int32_t xp = 0; xp < SpriteSize && x + xp < 256; xp++)
|
||||
{
|
||||
if (x + xp < 0) continue;
|
||||
if (LargeSprites && xp == OneCellSize)
|
||||
|
@ -1038,30 +1038,30 @@ namespace MSXHawk
|
|||
|
||||
void RenderTmsSpritesDouble(bool show)
|
||||
{
|
||||
for (int i = 0; i < 256; i++)
|
||||
for (uint32_t i = 0; i < 256; i++)
|
||||
{
|
||||
ScanlinePriorityBuffer[i] = 0;
|
||||
}
|
||||
for (int i = 0; i < 256; i++)
|
||||
for (uint32_t i = 0; i < 256; i++)
|
||||
{
|
||||
SpriteCollisionBuffer[i] = 0;
|
||||
}
|
||||
|
||||
bool LargeSprites = EnableLargeSprites();
|
||||
|
||||
int SpriteSize = 8;
|
||||
int32_t SpriteSize = 8;
|
||||
if (LargeSprites) SpriteSize *= 2;
|
||||
SpriteSize *= 2; // because sprite magnification
|
||||
const int OneCellSize = 16; // once 8-pixel cell, doubled, will take 16 pixels
|
||||
const int32_t OneCellSize = 16; // once 8-pixel cell, doubled, will take 16 pixels
|
||||
|
||||
int NumSpritesOnScanline = 0;
|
||||
for (int i = 0; i < 32; i++)
|
||||
int32_t NumSpritesOnScanline = 0;
|
||||
for (int32_t i = 0; i < 32; i++)
|
||||
{
|
||||
int SpriteBase = TmsSpriteAttributeBase + (i * 4);
|
||||
int y = VRAM[SpriteBase++];
|
||||
int x = VRAM[SpriteBase++];
|
||||
int Pattern = VRAM[SpriteBase++];
|
||||
int Color = VRAM[SpriteBase];
|
||||
int32_t SpriteBase = TmsSpriteAttributeBase + (i * 4);
|
||||
int32_t y = VRAM[SpriteBase++];
|
||||
int32_t x = VRAM[SpriteBase++];
|
||||
int32_t Pattern = VRAM[SpriteBase++];
|
||||
int32_t Color = VRAM[SpriteBase];
|
||||
|
||||
if (y == 208) break; // terminator sprite
|
||||
if (y > 224) y -= 256; // sprite Y wrap
|
||||
|
@ -1078,12 +1078,12 @@ namespace MSXHawk
|
|||
}
|
||||
|
||||
if (LargeSprites) Pattern &= 0xFC; // 16x16 sprites forced to 4-uint8_t alignment
|
||||
int SpriteLine = ScanLine - y;
|
||||
int32_t SpriteLine = ScanLine - y;
|
||||
SpriteLine /= 2; // because of sprite magnification
|
||||
|
||||
uint8_t pv = VRAM[SpritePatternGeneratorBase + (Pattern * 8) + SpriteLine];
|
||||
|
||||
for (int xp = 0; xp < SpriteSize && x + xp < 256; xp++)
|
||||
for (int32_t xp = 0; (xp < SpriteSize) && ((x + xp) < 256); xp++)
|
||||
{
|
||||
if (x + xp < 0) continue;
|
||||
if (LargeSprites && xp == OneCellSize)
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue