aboutsummaryrefslogtreecommitdiff
path: root/source/fxemu.c
diff options
context:
space:
mode:
authorTwinaphex2017-08-26 09:09:41 +0200
committerGitHub2017-08-26 09:09:41 +0200
commit12b1ae1a13434dd0bdc5305d36811643306d8e3e (patch)
tree33e4229f9175a51e5fc309d05b5f83f3de19251f /source/fxemu.c
parentb94a8041a928f5018d753d21d62507c1511af8d4 (diff)
parent7becd31bfe9ba0cd77ed9dc034563e0ab513a8c9 (diff)
downloadsnesemu-12b1ae1a13434dd0bdc5305d36811643306d8e3e.tar.gz
snesemu-12b1ae1a13434dd0bdc5305d36811643306d8e3e.tar.bz2
snesemu-12b1ae1a13434dd0bdc5305d36811643306d8e3e.zip
Merge pull request #43 from jamsilva/master
SA1 and SuperFX improvements
Diffstat (limited to 'source/fxemu.c')
-rw-r--r--source/fxemu.c177
1 files changed, 50 insertions, 127 deletions
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 <string.h>
#include <stdio.h>
+#include <retro_inline.h>
+
/* 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 */