mirror of
https://github.com/dborth/snes9xgx.git
synced 2024-11-27 21:14:21 +01:00
f513ac5e2f
- Fix Chou Aniki. Remove hack. - Fix lines in License Stub
372 lines
11 KiB
C
372 lines
11 KiB
C
/*****************************************************************************\
|
|
Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
|
|
This file is licensed under the Snes9x License.
|
|
For further information, consult the LICENSE file in the root directory.
|
|
\*****************************************************************************/
|
|
|
|
#ifndef _FXINST_H_
|
|
#define _FXINST_H_
|
|
|
|
/*
|
|
* FxChip(GSU) register space specification
|
|
* (Register address space 3000-32ff)
|
|
*
|
|
* The 16 generic 16 bit registers:
|
|
* (Some have a special function in special circumstances)
|
|
* 3000 - R0 default source/destination register
|
|
* 3002 - R1 pixel plot X position register
|
|
* 3004 - R2 pixel plot Y position register
|
|
* 3006 - R3
|
|
* 3008 - R4 lower 16 bit result of lmult
|
|
* 300a - R5
|
|
* 300c - R6 multiplier for fmult and lmult
|
|
* 300e - R7 fixed point texel X position for merge
|
|
* 3010 - R8 fixed point texel Y position for merge
|
|
* 3012 - R9
|
|
* 3014 - R10
|
|
* 3016 - R11 return address set by link
|
|
* 3018 - R12 loop counter
|
|
* 301a - R13 loop point address
|
|
* 301c - R14 rom address for getb, getbh, getbl, getbs
|
|
* 301e - R15 program counter
|
|
*
|
|
* 3020-302f - unused
|
|
*
|
|
* Other internal registers
|
|
* 3030 - SFR status flag register (16bit)
|
|
* 3032 - unused
|
|
* 3033 - BRAMR Backup RAM register (8bit)
|
|
* 3034 - PBR program bank register (8bit)
|
|
* 3035 - unused
|
|
* 3036 - ROMBR rom bank register (8bit)
|
|
* 3037 - CFGR control flags register (8bit)
|
|
* 3038 - SCBR screen base register (8bit)
|
|
* 3039 - CLSR clock speed register (8bit)
|
|
* 303a - SCMR screen mode register (8bit)
|
|
* 303b - VCR version code register (8bit) (read only)
|
|
* 303c - RAMBR ram bank register (8bit)
|
|
* 303d - unused
|
|
* 303e - CBR cache base register (16bit)
|
|
*
|
|
* 3040-30ff - unused
|
|
*
|
|
* 3100-32ff - CACHERAM 512 bytes of GSU cache memory
|
|
*
|
|
* SFR status flag register bits:
|
|
* 0 -
|
|
* 1 Z Zero flag
|
|
* 2 CY Carry flag
|
|
* 3 S Sign flag
|
|
* 4 OV Overflow flag
|
|
* 5 G Go flag (set to 1 when the GSU is running)
|
|
* 6 R Set to 1 when reading ROM using R14 address
|
|
* 7 -
|
|
* 8 ALT1 Mode set-up flag for the next instruction
|
|
* 9 ALT2 Mode set-up flag for the next instruction
|
|
* 10 IL Immediate lower 8-bit flag
|
|
* 11 IH Immediate higher 8-bit flag
|
|
* 12 B Set to 1 when the WITH instruction is executed
|
|
* 13 -
|
|
* 14 -
|
|
* 15 IRQ Set to 1 when GSU caused an interrupt
|
|
* Set to 0 when read by 658c16
|
|
*
|
|
* BRAMR = 0, BackupRAM is disabled
|
|
* BRAMR = 1, BackupRAM is enabled
|
|
*
|
|
* CFGR control flags register bits:
|
|
* 0 -
|
|
* 1 -
|
|
* 2 -
|
|
* 3 -
|
|
* 4 -
|
|
* 5 MS0 Multiplier speed, 0=standard, 1=high speed
|
|
* 6 -
|
|
* 7 IRQ Set to 1 when GSU interrupt request is masked
|
|
*
|
|
* CLSR clock speed register bits:
|
|
* 0 CLSR clock speed, 0 = 10.7Mhz, 1 = 21.4Mhz
|
|
*
|
|
* SCMR screen mode register bits:
|
|
* 0 MD0 color depth mode bit 0
|
|
* 1 MD1 color depth mode bit 1
|
|
* 2 HT0 screen height bit 1
|
|
* 3 RAN RAM access control
|
|
* 4 RON ROM access control
|
|
* 5 HT1 screen height bit 2
|
|
* 6 -
|
|
* 7 -
|
|
*
|
|
* RON = 0 SNES CPU has ROM access
|
|
* RON = 1 GSU has ROM access
|
|
*
|
|
* RAN = 0 SNES has game pak RAM access
|
|
* RAN = 1 GSU has game pak RAM access
|
|
*
|
|
* HT1 HT0 Screen height mode
|
|
* 0 0 128 pixels high
|
|
* 0 1 160 pixels high
|
|
* 1 0 192 pixels high
|
|
* 1 1 OBJ mode
|
|
*
|
|
* MD1 MD0 Color depth mode
|
|
* 0 0 4 color mode
|
|
* 0 1 16 color mode
|
|
* 1 0 not used
|
|
* 1 1 256 color mode
|
|
*
|
|
* CBR cache base register bits:
|
|
* 15-4 Specify base address for data to cache from ROM or RAM
|
|
* 3-0 Are 0 when address is read
|
|
*
|
|
* Write access to the program counter (301e) from
|
|
* the SNES-CPU will start the GSU, and it will not
|
|
* stop until it reaches a stop instruction.
|
|
*
|
|
*/
|
|
|
|
// Number of banks in GSU RAM
|
|
#define FX_RAM_BANKS 4
|
|
|
|
// Emulate proper R14 ROM access (slower, but safer)
|
|
#define FX_DO_ROMBUFFER
|
|
|
|
// Address checking (definately slow)
|
|
//#define FX_ADDRESS_CHECK
|
|
|
|
struct FxRegs_s
|
|
{
|
|
// FxChip registers
|
|
uint32 avReg[16]; // 16 Generic registers
|
|
uint32 vColorReg; // Internal color register
|
|
uint32 vPlotOptionReg; // Plot option register
|
|
uint32 vStatusReg; // Status register
|
|
uint32 vPrgBankReg; // Program bank index register
|
|
uint32 vRomBankReg; // Rom bank index register
|
|
uint32 vRamBankReg; // Ram bank index register
|
|
uint32 vCacheBaseReg; // Cache base address register
|
|
uint32 vCacheFlags; // Saying what parts of the cache was written to
|
|
uint32 vLastRamAdr; // Last RAM address accessed
|
|
uint32 *pvDreg; // Pointer to current destination register
|
|
uint32 *pvSreg; // Pointer to current source register
|
|
uint8 vRomBuffer; // Current byte read by R14
|
|
uint8 vPipe; // Instructionset pipe
|
|
uint32 vPipeAdr; // The address of where the pipe was read from
|
|
|
|
// Status register optimization stuff
|
|
uint32 vSign; // v & 0x8000
|
|
uint32 vZero; // v == 0
|
|
uint32 vCarry; // a value of 1 or 0
|
|
int32 vOverflow; // (v >= 0x8000 || v < -0x8000)
|
|
|
|
// Other emulator variables
|
|
int32 vErrorCode;
|
|
uint32 vIllegalAddress;
|
|
|
|
uint8 bBreakPoint;
|
|
uint32 vBreakPoint;
|
|
uint32 vStepPoint;
|
|
|
|
uint8 *pvRegisters; // 768 bytes located in the memory at address 0x3000
|
|
uint32 nRamBanks; // Number of 64kb-banks in FxRam (Don't confuse it with SNES-Ram!!!)
|
|
uint8 *pvRam; // Pointer to FxRam
|
|
uint32 nRomBanks; // Number of 32kb-banks in Cart-ROM
|
|
uint8 *pvRom; // Pointer to Cart-ROM
|
|
|
|
uint32 vMode; // Color depth/mode
|
|
uint32 vPrevMode; // Previous depth
|
|
uint8 *pvScreenBase;
|
|
uint8 *apvScreen[32]; // Pointer to each of the 32 screen colums
|
|
int32 x[32];
|
|
uint32 vScreenHeight; // 128, 160, 192 or 256 (could be overriden by cmode)
|
|
uint32 vScreenRealHeight; // 128, 160, 192 or 256
|
|
uint32 vPrevScreenHeight;
|
|
uint32 vScreenSize;
|
|
void (*pfPlot) (void);
|
|
void (*pfRpix) (void);
|
|
|
|
uint8 *pvRamBank; // Pointer to current RAM-bank
|
|
uint8 *pvRomBank; // Pointer to current ROM-bank
|
|
uint8 *pvPrgBank; // Pointer to current program ROM-bank
|
|
|
|
uint8 *apvRamBank[FX_RAM_BANKS]; // Ram bank table (max 256kb)
|
|
uint8 *apvRomBank[256]; // Rom bank table
|
|
|
|
uint8 bCacheActive;
|
|
uint8 *pvCache; // Pointer to the GSU cache
|
|
uint8 avCacheBackup[512]; // Backup of ROM when the cache has replaced it
|
|
uint32 vCounter;
|
|
uint32 vInstCount;
|
|
uint32 vSCBRDirty; // If SCBR is written, our cached screen pointers need updating
|
|
|
|
uint8 *avRegAddr; // To reference avReg in snapshot.cpp
|
|
};
|
|
|
|
extern struct FxRegs_s GSU;
|
|
|
|
// GSU registers
|
|
#define GSU_R0 0x000
|
|
#define GSU_R1 0x002
|
|
#define GSU_R2 0x004
|
|
#define GSU_R3 0x006
|
|
#define GSU_R4 0x008
|
|
#define GSU_R5 0x00a
|
|
#define GSU_R6 0x00c
|
|
#define GSU_R7 0x00e
|
|
#define GSU_R8 0x010
|
|
#define GSU_R9 0x012
|
|
#define GSU_R10 0x014
|
|
#define GSU_R11 0x016
|
|
#define GSU_R12 0x018
|
|
#define GSU_R13 0x01a
|
|
#define GSU_R14 0x01c
|
|
#define GSU_R15 0x01e
|
|
#define GSU_SFR 0x030
|
|
#define GSU_BRAMR 0x033
|
|
#define GSU_PBR 0x034
|
|
#define GSU_ROMBR 0x036
|
|
#define GSU_CFGR 0x037
|
|
#define GSU_SCBR 0x038
|
|
#define GSU_CLSR 0x039
|
|
#define GSU_SCMR 0x03a
|
|
#define GSU_VCR 0x03b
|
|
#define GSU_RAMBR 0x03c
|
|
#define GSU_CBR 0x03e
|
|
#define GSU_CACHERAM 0x100
|
|
|
|
// SFR flags
|
|
#define FLG_Z (1 << 1)
|
|
#define FLG_CY (1 << 2)
|
|
#define FLG_S (1 << 3)
|
|
#define FLG_OV (1 << 4)
|
|
#define FLG_G (1 << 5)
|
|
#define FLG_R (1 << 6)
|
|
#define FLG_ALT1 (1 << 8)
|
|
#define FLG_ALT2 (1 << 9)
|
|
#define FLG_IL (1 << 10)
|
|
#define FLG_IH (1 << 11)
|
|
#define FLG_B (1 << 12)
|
|
#define FLG_IRQ (1 << 15)
|
|
|
|
// Test flag
|
|
#define TF(a) (GSU.vStatusReg & FLG_##a)
|
|
#define CF(a) (GSU.vStatusReg &= ~FLG_##a)
|
|
#define SF(a) (GSU.vStatusReg |= FLG_##a)
|
|
|
|
// Test and set flag if condition, clear if not
|
|
#define TS(a, b) GSU.vStatusReg = ((GSU.vStatusReg & (~FLG_##a)) | ((!!(##b)) * FLG_##a))
|
|
|
|
// Testing ALT1 & ALT2 bits
|
|
#define ALT0 (!TF(ALT1) && !TF(ALT2))
|
|
#define ALT1 ( TF(ALT1) && !TF(ALT2))
|
|
#define ALT2 (!TF(ALT1) && TF(ALT2))
|
|
#define ALT3 ( TF(ALT1) && TF(ALT2))
|
|
|
|
// Sign extend from 8/16 bit to 32 bit
|
|
#define SEX8(a) ((int32) ((int8) (a)))
|
|
#define SEX16(a) ((int32) ((int16) (a)))
|
|
|
|
// Unsign extend from 8/16 bit to 32 bit
|
|
#define USEX8(a) ((uint32) ((uint8) (a)))
|
|
#define USEX16(a) ((uint32) ((uint16) (a)))
|
|
#define SUSEX16(a) ((int32) ((uint16) (a)))
|
|
|
|
// Set/Clr Sign and Zero flag
|
|
#define TSZ(num) TS(S, ((num) & 0x8000)); TS(Z, (!USEX16(num)))
|
|
|
|
// Clear flags
|
|
#define CLRFLAGS GSU.vStatusReg &= ~(FLG_ALT1 | FLG_ALT2 | FLG_B); GSU.pvDreg = GSU.pvSreg = &R0
|
|
|
|
// Read current RAM-Bank
|
|
#define RAM(adr) GSU.pvRamBank[USEX16(adr)]
|
|
|
|
// Read current ROM-Bank
|
|
#define ROM(idx) GSU.pvRomBank[USEX16(idx)]
|
|
|
|
// Access the current value in the pipe
|
|
#define PIPE GSU.vPipe
|
|
|
|
// Access data in the current program bank
|
|
#define PRGBANK(idx) GSU.pvPrgBank[USEX16(idx)]
|
|
|
|
// Update pipe from ROM
|
|
#if 0
|
|
#define FETCHPIPE { PIPE = PRGBANK(R15); GSU.vPipeAdr = (GSU.vPrgBankReg << 16) + R15; }
|
|
#else
|
|
#define FETCHPIPE { PIPE = PRGBANK(R15); }
|
|
#endif
|
|
|
|
// ABS
|
|
#define ABS(x) ((x) < 0 ? -(x) : (x))
|
|
|
|
// Access source register
|
|
#define SREG (*GSU.pvSreg)
|
|
|
|
// Access destination register
|
|
#define DREG (*GSU.pvDreg)
|
|
|
|
#ifndef FX_DO_ROMBUFFER
|
|
|
|
// Don't read R14
|
|
#define READR14
|
|
|
|
// Don't test and/or read R14
|
|
#define TESTR14
|
|
|
|
#else
|
|
|
|
// Read R14
|
|
#define READR14 GSU.vRomBuffer = ROM(R14)
|
|
|
|
// Test and/or read R14
|
|
#define TESTR14 if (GSU.pvDreg == &R14) READR14
|
|
|
|
#endif
|
|
|
|
// Access to registers
|
|
#define R0 GSU.avReg[0]
|
|
#define R1 GSU.avReg[1]
|
|
#define R2 GSU.avReg[2]
|
|
#define R3 GSU.avReg[3]
|
|
#define R4 GSU.avReg[4]
|
|
#define R5 GSU.avReg[5]
|
|
#define R6 GSU.avReg[6]
|
|
#define R7 GSU.avReg[7]
|
|
#define R8 GSU.avReg[8]
|
|
#define R9 GSU.avReg[9]
|
|
#define R10 GSU.avReg[10]
|
|
#define R11 GSU.avReg[11]
|
|
#define R12 GSU.avReg[12]
|
|
#define R13 GSU.avReg[13]
|
|
#define R14 GSU.avReg[14]
|
|
#define R15 GSU.avReg[15]
|
|
#define SFR GSU.vStatusReg
|
|
#define PBR GSU.vPrgBankReg
|
|
#define ROMBR GSU.vRomBankReg
|
|
#define RAMBR GSU.vRamBankReg
|
|
#define CBR GSU.vCacheBaseReg
|
|
#define SCBR USEX8(GSU.pvRegisters[GSU_SCBR])
|
|
#define SCMR USEX8(GSU.pvRegisters[GSU_SCMR])
|
|
#define COLR GSU.vColorReg
|
|
#define POR GSU.vPlotOptionReg
|
|
#define BRAMR USEX8(GSU.pvRegisters[GSU_BRAMR])
|
|
#define VCR USEX8(GSU.pvRegisters[GSU_VCR])
|
|
#define CFGR USEX8(GSU.pvRegisters[GSU_CFGR])
|
|
#define CLSR USEX8(GSU.pvRegisters[GSU_CLSR])
|
|
|
|
// Execute instruction from the pipe, and fetch next byte to the pipe
|
|
#define FX_STEP \
|
|
{ \
|
|
uint32 vOpcode = (uint32) PIPE; \
|
|
FETCHPIPE; \
|
|
(*fx_OpcodeTable[(GSU.vStatusReg & 0x300) | vOpcode])(); \
|
|
}
|
|
|
|
extern void (*fx_PlotTable[]) (void);
|
|
extern void (*fx_OpcodeTable[]) (void);
|
|
|
|
// Set this define if branches are relative to the instruction in the delay slot (I think they are)
|
|
#define BRANCH_DELAY_RELATIVE
|
|
|
|
#endif
|