From b467f7ba0517823d6de4a08684484760bb1bf99a Mon Sep 17 00:00:00 2001 From: João Silva Date: Sat, 26 Aug 2017 00:22:32 +0100 Subject: SuperFX fixes and improvements, some from snes9x2010. --- source/fxemu.c | 177 ++++++++++++++++----------------------------------------- 1 file changed, 50 insertions(+), 127 deletions(-) (limited to 'source/fxemu.c') diff --git a/source/fxemu.c b/source/fxemu.c index dd798fd..9d62b05 100644 --- a/source/fxemu.c +++ b/source/fxemu.c @@ -6,6 +6,8 @@ #include #include +#include + /* The FxChip Emulator's internal variables */ FxRegs_s GSU; /* This will be initialized when loading a ROM */ @@ -27,13 +29,10 @@ void fx_updateRamBank(uint8_t Byte) GSU.pvRamBank = GSU.apvRamBank[Byte & 0x3]; } -static void fx_readRegisterSpaceForCheck(void) +static INLINE void fx_readRegisterSpaceForCheck(void) { R15 = GSU.pvRegisters[30]; R15 |= ((uint32_t) GSU.pvRegisters[31]) << 8; - GSU.vStatusReg = (uint32_t) GSU.pvRegisters[GSU_SFR]; - GSU.vStatusReg |= ((uint32_t) GSU.pvRegisters[GSU_SFR + 1]) << 8; - GSU.vPrgBankReg = (uint32_t) GSU.pvRegisters[GSU_PBR]; } static void fx_readRegisterSpaceForUse(void) @@ -52,6 +51,9 @@ static void fx_readRegisterSpaceForUse(void) /* Update other registers */ p = GSU.pvRegisters; + GSU.vStatusReg = (uint32_t) GSU.pvRegisters[GSU_SFR]; + GSU.vStatusReg |= ((uint32_t) GSU.pvRegisters[GSU_SFR + 1]) << 8; + GSU.vPrgBankReg = (uint32_t) GSU.pvRegisters[GSU_PBR]; GSU.vRomBankReg = (uint32_t)p[GSU_ROMBR]; GSU.vRamBankReg = ((uint32_t)p[GSU_RAMBR]) & (FX_RAM_BANKS - 1); GSU.vCacheBaseReg = (uint32_t)p[GSU_CBR]; @@ -75,9 +77,9 @@ static void fx_readRegisterSpaceForUse(void) GSU.vScreenHeight = GSU.vScreenRealHeight = avHeight[i]; GSU.vMode = p[GSU_SCMR] & 0x03; if (i == 3) - GSU.vScreenSize = (256 / 8) * (256 / 8) * 32; + GSU.vScreenSize = 32768; else - GSU.vScreenSize = (GSU.vScreenHeight / 8) * (256 / 8) * avMult[GSU.vMode]; + GSU.vScreenSize = GSU.vScreenHeight * 4 * avMult[GSU.vMode]; if (GSU.vPlotOptionReg & 0x10) GSU.vScreenHeight = 256; /* OBJ Mode (for drawing into sprites) */ if (GSU.pvScreenBase + GSU.vScreenSize > GSU.pvRam + (GSU.nRamBanks * 65536)) @@ -90,7 +92,8 @@ static void fx_readRegisterSpaceForUse(void) fx_apfOpcodeTable[0x24c] = GSU.pfPlot; fx_apfOpcodeTable[0x34c] = GSU.pfRpix; - fx_computeScreenPointers(); + if(GSU.vMode != GSU.vPrevMode || GSU.vPrevScreenHeight != GSU.vScreenHeight || GSU.vSCBRDirty) + fx_computeScreenPointers(); } void fx_dirtySCBR(void) @@ -100,135 +103,52 @@ void fx_dirtySCBR(void) void fx_computeScreenPointers(void) { - if (GSU.vMode != GSU.vPrevMode || GSU.vPrevScreenHeight != GSU.vScreenHeight || GSU.vSCBRDirty) + int32_t i, j, condition, mask, result; + uint32_t apvIncrement, vMode, xIncrement; + GSU.vSCBRDirty = false; + + /* Make a list of pointers to the start of each screen column*/ + vMode = GSU.vMode; + condition = vMode - 2; + mask = (condition | -condition) >> 31; + result = (vMode & mask) | (3 & ~mask); + vMode = result + 1; + GSU.x[0] = 0; + GSU.apvScreen[0] = GSU.pvScreenBase; + apvIncrement = vMode << 4; + + if(GSU.vScreenHeight == 256) { - int32_t i; - GSU.vSCBRDirty = false; + GSU.x[16] = vMode << 12; + GSU.apvScreen[16] = GSU.pvScreenBase + (vMode << 13); + apvIncrement <<= 4; + xIncrement = vMode << 4; - /* Make a list of pointers to the start of each screen column */ - switch (GSU.vScreenHeight) + for(i = 1, j = 17 ; i < 16 ; i++, j++) + { + GSU.x[i] = GSU.x[i - 1] + xIncrement; + GSU.apvScreen[i] = GSU.apvScreen[i - 1] + apvIncrement; + GSU.x[j] = GSU.x[j - 1] + xIncrement; + GSU.apvScreen[j] = GSU.apvScreen[j - 1] + apvIncrement; + } + } + else + { + xIncrement = (vMode * GSU.vScreenHeight) << 1; + for(i = 1 ; i < 32 ; i++) { - case 128: - switch (GSU.vMode) - { - case 0: - for (i = 0; i < 32; i++) - { - GSU.apvScreen[i] = GSU.pvScreenBase + (i << 4); - GSU.x[i] = i << 8; - } - break; - case 1: - for (i = 0; i < 32; i++) - { - GSU.apvScreen[i] = GSU.pvScreenBase + (i << 5); - GSU.x[i] = i << 9; - } - break; - case 2: - case 3: - for (i = 0; i < 32; i++) - { - GSU.apvScreen[i] = GSU.pvScreenBase + (i << 6); - GSU.x[i] = i << 10; - } - break; - } - break; - case 160: - switch (GSU.vMode) - { - case 0: - for (i = 0; i < 32; i++) - { - GSU.apvScreen[i] = GSU.pvScreenBase + (i << 4); - GSU.x[i] = (i << 8) + (i << 6); - } - break; - case 1: - for (i = 0; i < 32; i++) - { - GSU.apvScreen[i] = GSU.pvScreenBase + (i << 5); - GSU.x[i] = (i << 9) + (i << 7); - } - break; - case 2: - case 3: - for (i = 0; i < 32; i++) - { - GSU.apvScreen[i] = GSU.pvScreenBase + (i << 6); - GSU.x[i] = (i << 10) + (i << 8); - } - break; - } - break; - case 192: - switch (GSU.vMode) - { - case 0: - for (i = 0; i < 32; i++) - { - GSU.apvScreen[i] = GSU.pvScreenBase + (i << 4); - GSU.x[i] = (i << 8) + (i << 7); - } - break; - case 1: - for (i = 0; i < 32; i++) - { - GSU.apvScreen[i] = GSU.pvScreenBase + (i << 5); - GSU.x[i] = (i << 9) + (i << 8); - } - break; - case 2: - case 3: - for (i = 0; i < 32; i++) - { - GSU.apvScreen[i] = GSU.pvScreenBase + (i << 6); - GSU.x[i] = (i << 10) + (i << 9); - } - break; - } - break; - case 256: - switch (GSU.vMode) - { - case 0: - for (i = 0; i < 32; i++) - { - GSU.apvScreen[i] = GSU.pvScreenBase + ((i & 0x10) << 9) + ((i & 0xf) << 8); - GSU.x[i] = ((i & 0x10) << 8) + ((i & 0xf) << 4); - } - break; - case 1: - for (i = 0; i < 32; i++) - { - GSU.apvScreen[i] = GSU.pvScreenBase + ((i & 0x10) << 10) + ((i & 0xf) << 9); - GSU.x[i] = ((i & 0x10) << 9) + ((i & 0xf) << 5); - } - break; - case 2: - case 3: - for (i = 0; i < 32; i++) - { - GSU.apvScreen[i] = GSU.pvScreenBase + ((i & 0x10) << 11) + ((i & 0xf) << 10); - GSU.x[i] = ((i & 0x10) << 10) + ((i & 0xf) << 6); - } - break; - } - break; + GSU.x[i] = GSU.x[i - 1] + xIncrement; + GSU.apvScreen[i] = GSU.apvScreen[i - 1] + apvIncrement; } - GSU.vPrevMode = GSU.vMode; - GSU.vPrevScreenHeight = GSU.vScreenHeight; } + GSU.vPrevMode = GSU.vMode; + GSU.vPrevScreenHeight = GSU.vScreenHeight; } -static void fx_writeRegisterSpaceAfterCheck(void) +static INLINE void fx_writeRegisterSpaceAfterCheck(void) { GSU.pvRegisters[30] = (uint8_t) R15; GSU.pvRegisters[31] = (uint8_t) (R15 >> 8); - GSU.pvRegisters[GSU_SFR] = (uint8_t) GSU.vStatusReg; - GSU.pvRegisters[GSU_SFR + 1] = (uint8_t) (GSU.vStatusReg >> 8); - GSU.pvRegisters[GSU_PBR] = (uint8_t) GSU.vPrgBankReg; } static void fx_writeRegisterSpaceAfterUse(void) @@ -260,6 +180,9 @@ static void fx_writeRegisterSpaceAfterUse(void) CF(CY); p = GSU.pvRegisters; + p[GSU_SFR] = (uint8_t) GSU.vStatusReg; + p[GSU_SFR + 1] = (uint8_t) (GSU.vStatusReg >> 8); + p[GSU_PBR] = (uint8_t) GSU.vPrgBankReg; p[GSU_ROMBR] = (uint8_t)GSU.vRomBankReg; p[GSU_RAMBR] = (uint8_t)GSU.vRamBankReg; p[GSU_CBR] = (uint8_t)GSU.vCacheBaseReg; @@ -342,7 +265,7 @@ static bool fx_checkStartAddress(void) return false; /* Check if we're in RAM and the RAN flag is not set */ - if (GSU.vPrgBankReg >= 0x70 && GSU.vPrgBankReg <= 0x73 && !(SCMR & (1 << 3))) + if (GSU.vPrgBankReg >= 0x70 && !(SCMR & (1 << 3))) return false; /* If not, we're in ROM, so check if the RON flag is set */ -- cgit v1.2.3