beetle-pce-fast-libretro/mednafen/pce_fast/huc6280.c

761 lines
21 KiB
C
Raw Permalink Normal View History

2013-01-16 14:22:03 +00:00
/* Mednafen - Multi-system Emulator
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
2020-09-16 18:52:38 +00:00
#include <stdint.h>
#include <string.h>
2020-10-04 15:00:42 +00:00
#include <boolean.h>
2020-09-16 18:52:38 +00:00
2013-01-16 14:22:03 +00:00
#include "pce.h"
#include "vdc.h"
2020-07-05 18:13:04 +00:00
#include "../state_helpers.h"
2013-01-16 14:22:03 +00:00
2020-10-04 15:00:42 +00:00
bool PCE_IsCD;
2020-10-04 14:43:04 +00:00
int pce_overclocked;
static uint8 dummy_bank[8192 + 8192]; // + 8192 for PC-as-ptr safety padding
2020-10-04 14:43:04 +00:00
struct HuC6280 HuCPU;
2013-01-16 14:22:03 +00:00
#define HU_PC PC_local //HuCPU.PC
#define HU_PC_base HuCPU.PC_base
#define HU_A HuCPU.A
#define HU_X X_local //HuCPU.X
#define HU_Y Y_local //HuCPU.Y
#define HU_S HuCPU.S
#define HU_P P_local //HuCPU.P
#define HU_PI HuCPU.mooPI
#define HU_IRQlow HuCPU.IRQlow
#define HU_Page1 Page1_local
//HuCPU.Page1
//Page1_local //HuCPU.Page1
#ifdef HUC6280_LAZY_FLAGS
#define HU_ZNFlags HuCPU.ZNFlags
#endif
#ifdef HUC6280_CRAZY_VERSION
#define LOAD_LOCALS_PC() uintptr_t PC_local = HuCPU.PC;
2013-01-16 14:22:03 +00:00
#else
2019-12-15 07:36:44 +00:00
#define LOAD_LOCALS_PC() uint32 PC_local /*asm ("edi")*/ = HuCPU.PC; // asm ("edi") = HuCPU.PC;
2013-01-16 14:22:03 +00:00
#endif
#define LOAD_LOCALS() \
#define SAVE_LOCALS() HuCPU.PC = PC_local; \
HuCPU.X = X_local; \
HuCPU.Y = Y_local; \
HuCPU.P = P_local; \
HuCPU.Page1 = Page1_local;
#ifdef HUC6280_LAZY_FLAGS
#define COMPRESS_FLAGS() HU_P &= ~(N_FLAG | Z_FLAG); HU_P |= ((HU_ZNFlags >> 24) & 0x80) | ((HU_ZNFlags & 0xFF) ? 0 : Z_FLAG);
//((((HU_ZNFlags & 0xFF) - 1) >> 8) & Z_FLAG);
#define EXPAND_FLAGS() HU_ZNFlags = (HU_P << 24) | ((HU_P & Z_FLAG) ^ Z_FLAG);
#else
#define COMPRESS_FLAGS()
#define EXPAND_FLAGS()
#endif
#ifdef HUC6280_CRAZY_VERSION
#define GetRealPC() ((unsigned int)(HU_PC - HU_PC_base))
#define GetRealPC_EXTERNAL() ((unsigned int)(HuCPU.PC - HuCPU.PC_base))
#else
#define GetRealPC() (HU_PC)
#define GetRealPC_EXTERNAL() (HuCPU.PC)
#endif
#ifdef HUC6280_CRAZY_VERSION
#define SetPC(value) { unsigned int tempmoo = value; HU_PC = HuCPU.FastPageR[tempmoo >> 13] + tempmoo; \
2013-01-16 14:22:03 +00:00
HU_PC_base = HU_PC - tempmoo; }
#define SetPC_EXTERNAL(value) { unsigned int tempmoo = value; \
HuCPU.PC = HuCPU.FastPageR[tempmoo >> 13] + tempmoo; HuCPU.PC_base = HuCPU.PC - tempmoo; }
2013-01-16 14:22:03 +00:00
#else
#define SetPC(value) { HU_PC = (value); }
#define SetPC_EXTERNAL(value) { HuCPU.PC = (value); }
#endif
// Page change PC, GET IT?!
#ifdef HUC6280_CRAZY_VERSION
#define FixPC_PC() SetPC(GetRealPC());
#else
#define FixPC_PC()
#endif
#define IncPC() HU_PC++;
#ifdef HUC6280_CRAZY_VERSION
#define RdAtPC() (*(uint8*)HU_PC)
2013-01-16 14:22:03 +00:00
#else
#define RdAtPC() RdOp(HU_PC)
#endif
// If we change this definition, we'll need to also fix HuC6280_StealCycle() in huc6280.h
#define ADDCYC(x) { HuCPU.timestamp += x; }
#define SET_MPR(arg_i, arg_v) \
{ \
const unsigned int wmpr = arg_i, wbank = arg_v; \
if(wmpr == 1) \
{ \
HU_Page1 = HuCPU.FastMap[wbank]; \
2013-01-16 14:22:03 +00:00
} \
HuCPU.MPR[wmpr] = wbank; \
HuCPU.FastPageR[wmpr] = (uintptr_t)HuCPU.FastMap[wbank] - wmpr * 8192; \
2013-01-16 14:22:03 +00:00
}
void HuC6280_SetMPR(int i, int v)
{
2015-07-25 02:21:22 +00:00
uint8 *Page1_local = HuCPU.Page1;
2013-01-16 14:22:03 +00:00
2015-07-25 02:21:22 +00:00
SET_MPR(i, v);
2013-01-16 14:22:03 +00:00
2015-07-25 02:21:22 +00:00
HuCPU.Page1 = Page1_local;
2013-01-16 14:22:03 +00:00
}
static void HuC6280_FlushMPRCache(void)
{
2020-10-04 14:43:04 +00:00
int x;
for(x = 0; x < 9; x++)
2015-07-25 02:21:22 +00:00
HuC6280_SetMPR(x, HuCPU.MPR[x & 0x7]);
2013-01-16 14:22:03 +00:00
}
static INLINE uint8 RdMem(unsigned int A)
{
2015-07-25 02:21:22 +00:00
uint8 wmpr = HuCPU.MPR[A >> 13];
return(HuCPU.PCERead[wmpr]((wmpr << 13) | (A & 0x1FFF)));
2013-01-16 14:22:03 +00:00
}
static INLINE uint16 RdMem16(unsigned int A)
{
uint16 ret;
ret = RdMem(A);
ret |= RdMem(A + 1) << 8;
return(ret);
2013-01-16 14:22:03 +00:00
}
static INLINE void WrMem(unsigned int A, uint8 V)
{
2015-07-25 02:21:22 +00:00
uint8 wmpr = HuCPU.MPR[A >> 13];
HuCPU.PCEWrite[wmpr]((wmpr << 13) | (A & 0x1FFF), V);
2013-01-16 14:22:03 +00:00
}
static INLINE uint8 RdOp(unsigned int A)
{
return *(uint8*)(HuCPU.FastPageR[A >> 13] + A);
2013-01-16 14:22:03 +00:00
}
#define PUSH(V) \
{ \
2015-07-25 02:21:22 +00:00
HU_Page1[0x100 + HU_S] = V; \
HU_S--; \
2013-01-16 14:22:03 +00:00
}
#define PUSH_PC() \
{ \
2015-07-25 02:21:22 +00:00
unsigned int real_pc = GetRealPC(); \
PUSH(real_pc >> 8); \
PUSH(real_pc); \
2013-01-16 14:22:03 +00:00
}
#define POP() HU_Page1[0x100 + ++HU_S]
#define POP_PC() \
{ \
2015-07-25 02:21:22 +00:00
unsigned int npc; \
npc = POP(); \
npc |= POP() << 8; \
SetPC(npc); \
2013-01-16 14:22:03 +00:00
}
// Hopefully we never RTS to 0x0000. ;)
#define POP_PC_AP() \
{ \
2015-07-25 02:21:22 +00:00
uint32 npc; \
npc = POP(); \
npc |= POP() << 8; \
npc++; \
SetPC(npc); \
2013-01-16 14:22:03 +00:00
}
/* Some of these operations will only make sense if you know what the flag
constants are. */
#ifdef HUC6280_LAZY_FLAGS
2015-07-25 02:21:22 +00:00
#define X_ZN(zort) { HU_ZNFlags = (int32)(int8)(uint8)(zort); }
#define X_ZN_BIT(opres, argie) { HU_ZNFlags = (opres) | ((argie) << 24); }
2013-01-16 14:22:03 +00:00
#else
2015-07-25 02:21:22 +00:00
static uint8 ZNTable[256];
#define X_ZN(zort) HU_P&=~(Z_FLAG|N_FLAG);HU_P|=ZNTable[zort]
#define X_ZN_BIT(opres, argie) { HU_P &= ~(Z_FLAG | N_FLAG); HU_P |= ZNTable[opres] & Z_FLAG; HU_P |= argie & N_FLAG; }
2013-01-16 14:22:03 +00:00
#endif
#define JR(cond) \
{ \
2015-07-25 02:21:22 +00:00
if(cond) \
{ \
int32 disp; \
disp = 1 + (int8)RdAtPC(); \
ADDCYC(2); \
HU_PC+=disp; \
} \
else IncPC(); \
2013-01-16 14:22:03 +00:00
}
#define BRA \
{ \
2015-07-25 02:21:22 +00:00
int32 disp; \
disp = 1 + (int8)RdAtPC(); \
HU_PC+=disp; \
2013-01-16 14:22:03 +00:00
}
#define BBRi(bitto) JR(!(x & (1 << bitto)))
#define BBSi(bitto) JR(x & (1 << bitto))
#define ST0 VDC_Write_ST(0, x)
#define ST1 VDC_Write_ST(2, x)
#define ST2 VDC_Write_ST(3, x)
#define LDA HU_A=x;X_ZN(HU_A)
#define LDX HU_X=x;X_ZN(HU_X)
#define LDY HU_Y=x;X_ZN(HU_Y)
/* All of the freaky arithmetic operations. */
#define AND HU_A&=x;X_ZN(HU_A);
#define BIT HU_P&=~V_FLAG; X_ZN_BIT(x & HU_A, x); HU_P |= x & V_FLAG;
#define EOR HU_A^=x;X_ZN(HU_A);
#define ORA HU_A|=x;X_ZN(HU_A);
#define ADC { \
2015-07-25 02:21:22 +00:00
if(HU_P & D_FLAG) \
{ \
2016-04-12 20:35:26 +00:00
uint32 tmp; \
tmp = (HU_A & 0x0F) + (x & 0x0F) + (HU_P & 1); \
if(tmp >= 0x0A) \
tmp += 0x06; \
tmp += (HU_A & 0xF0) + (x & 0xF0); \
if(tmp >= 0xA0) \
tmp += 0x60; \
HU_P &= ~C_FLAG; \
if(tmp & 0xFF00) \
HU_P |= C_FLAG; \
HU_A = tmp; \
X_ZN(HU_A); \
2015-07-25 02:21:22 +00:00
} \
else \
{ \
uint32 l=HU_A+x+(HU_P&1); \
HU_P&=~(C_FLAG|V_FLAG); \
HU_P|=((((HU_A^x)&0x80)^0x80) & ((HU_A^l)&0x80))>>1; \
HU_P|=(l>>8)&C_FLAG; \
HU_A=l; \
X_ZN(HU_A); \
} \
}
2013-01-16 14:22:03 +00:00
#define SBC if(HU_P & D_FLAG) \
2015-07-25 02:21:22 +00:00
{ \
2016-04-12 20:35:26 +00:00
const uint8 m = (HU_A & 0xF) - (x & 0xF) - ((HU_P & 1) ^ 1); \
const uint8 n = (HU_A >> 4) - (x >> 4) - ((m >> 4) & 1); \
uint8 res = (n << 4) | (m & 0xF); \
if(m & 0x10) \
res -= 0x06; \
if(n & 0x10) \
res -= 0x60; \
HU_A = res; \
HU_P &= ~C_FLAG; \
HU_P |= ((n >> 4) & 0x1) ^ 1; \
X_ZN(HU_A); \
2015-07-25 02:21:22 +00:00
} else { \
uint32 l=HU_A-x-((HU_P&1)^1); \
HU_P&=~(C_FLAG|V_FLAG); \
HU_P|=((HU_A^l)&(HU_A^x)&0x80)>>1; \
HU_P|=((l>>8)&C_FLAG)^C_FLAG; \
HU_A=l; \
X_ZN(HU_A); \
}
2013-01-16 14:22:03 +00:00
#define CMPL(a1,a2) { \
2015-07-25 02:21:22 +00:00
uint32 t=a1-a2; \
X_ZN(t&0xFF); \
HU_P&=~C_FLAG; \
HU_P|=((t>>8)&C_FLAG)^C_FLAG; \
}
2013-01-16 14:22:03 +00:00
2020-10-04 14:43:04 +00:00
#define TAM \
for(i = 0; i < 8; i ++) { \
2015-07-25 02:21:22 +00:00
if(x & (1 << i)) \
{ \
SET_MPR(i, HU_A); \
} \
} SET_MPR(8, HuCPU.MPR[0]);
2013-01-16 14:22:03 +00:00
2020-10-04 14:43:04 +00:00
#define TMA \
for(i = 0; i < 8; i ++) { \
2015-07-25 02:21:22 +00:00
if(x & (1 << i)) \
HU_A = HuCPU.MPR[i]; \
}
2013-01-16 14:22:03 +00:00
#define CSL
#define CSH
#define RMB(bitto) x &= ~(1 << (bitto & 7))
#define SMB(bitto) x |= 1 << (bitto & 7)
#define TSB { HU_P &= ~V_FLAG; X_ZN_BIT(x | HU_A, x); HU_P |= x & V_FLAG; x |= HU_A; }
#define TRB { HU_P &= ~V_FLAG; X_ZN_BIT(x & ~HU_A, x); HU_P |= x & V_FLAG; x &= ~HU_A; }
#define TST { HU_P &= ~V_FLAG; X_ZN_BIT(x & zoomhack, x); HU_P |= x & V_FLAG; }
#define CMP CMPL(HU_A,x)
#define CPX CMPL(HU_X,x)
#define CPY CMPL(HU_Y,x)
/* The following operations modify the byte being worked on. */
#define DEC x--;X_ZN(x)
#define INC x++;X_ZN(x)
#define ASL HU_P&=~C_FLAG;HU_P|=x>>7;x<<=1;X_ZN(x)
#define LSR HU_P&=~C_FLAG;HU_P|=x&1;x>>=1;X_ZN(x)
#define ROL { \
2015-07-25 02:21:22 +00:00
uint8 l=x>>7; \
x<<=1; \
x|=HU_P&C_FLAG; \
HU_P&=~C_FLAG; \
HU_P|=l; \
X_ZN(x); \
}
2013-01-16 14:22:03 +00:00
#define ROR { \
2015-07-25 02:21:22 +00:00
uint8 l=x&1; \
x>>=1; \
x|=(HU_P&C_FLAG)<<7; \
HU_P&=~C_FLAG; \
HU_P|=l; \
X_ZN(x); \
}
2013-01-16 14:22:03 +00:00
/* Absolute */
#define GetAB(target) \
{ \
2015-07-25 02:21:22 +00:00
target=RdAtPC(); \
IncPC(); \
target|=RdAtPC()<<8; \
IncPC(); \
2013-01-16 14:22:03 +00:00
}
/* Absolute Indexed(for reads) */
#define GetABI(target, i) \
{ \
2015-07-25 02:21:22 +00:00
unsigned int tmp; \
GetAB(tmp); \
target=tmp; \
target+=i; \
2013-01-16 14:22:03 +00:00
}
/* Zero Page */
#define GetZP(target) \
{ \
2015-07-25 02:21:22 +00:00
target=RdAtPC(); \
IncPC(); \
2013-01-16 14:22:03 +00:00
}
/* Zero Page Indexed */
#define GetZPI(target,i) \
{ \
2015-07-25 02:21:22 +00:00
target=i+RdAtPC(); \
IncPC(); \
2013-01-16 14:22:03 +00:00
}
/* Indirect */
#define GetIND(target) \
{ \
2015-07-25 02:21:22 +00:00
uint8 tmp; \
tmp=RdAtPC(); \
IncPC(); \
target=HU_Page1[tmp]; \
tmp++; \
target|=HU_Page1[tmp]<<8; \
2013-01-16 14:22:03 +00:00
}
/* Indexed Indirect */
#define GetIX(target) \
{ \
2015-07-25 02:21:22 +00:00
uint8 tmp; \
tmp=RdAtPC(); \
IncPC(); \
tmp+=HU_X; \
target=HU_Page1[tmp]; \
tmp++; \
target|=HU_Page1[tmp] <<8; \
2013-01-16 14:22:03 +00:00
}
/* Indirect Indexed(for reads) */
#define GetIY(target) \
{ \
2015-07-25 02:21:22 +00:00
unsigned int rt; \
uint8 tmp; \
tmp=RdAtPC(); \
rt=HU_Page1[tmp]; \
tmp++; \
rt|=HU_Page1[tmp]<<8; \
target = (rt + HU_Y); \
IncPC(); \
2013-01-16 14:22:03 +00:00
}
/* Now come the macros to wrap up all of the above stuff addressing mode functions
and operation macros. Note that operation macros will always operate(redundant
redundant) on the variable "x".
2015-07-25 02:21:22 +00:00
*/
2013-01-16 14:22:03 +00:00
#define RMW_A(op) {uint8 x=HU_A; op; HU_A=x; break; } /* Meh... */
#define RMW_AB(op) {unsigned int EA; uint8 x; GetAB(EA); x=RdMem(EA); op; WrMem(EA,x); break; }
#define RMW_ABI(reg,op) {unsigned int EA; uint8 x; GetABI(EA,reg); x=RdMem(EA); op; WrMem(EA,x); break; }
#define RMW_ABX(op) RMW_ABI(HU_X,op)
#define RMW_ABY(op) RMW_ABI(HU_Y,op)
#define RMW_IND(op) { unsigned int EA; uint8 x; GetIND(EA); x = RdMem(EA); op; WrMem(EA, x); break; }
#define RMW_IX(op) { unsigned int EA; uint8 x; GetIX(EA); x=RdMem(EA); op; WrMem(EA,x); break; }
#define RMW_IY(op) { unsigned int EA; uint8 x; GetIY(EA); x=RdMem(EA); op; WrMem(EA,x); break; }
#define RMW_ZP(op) { uint8 EA; uint8 x; GetZP(EA); x=HU_Page1[EA]; op; HU_Page1[EA] = x; break; }
#define RMW_ZPX(op) { uint8 EA; uint8 x; GetZPI(EA,HU_X); x=HU_Page1[EA]; op; HU_Page1[EA] = x; break;}
#define LD_IM(op) { uint8 x; x=RdAtPC(); IncPC(); op; break; }
#define LD_ZP(op) { uint8 EA; uint8 x; GetZP(EA); x=HU_Page1[EA]; op; break; }
#define LD_ZPX(op) { uint8 EA; uint8 x; GetZPI(EA,HU_X); x=HU_Page1[EA]; op; break; }
#define LD_ZPY(op) { uint8 EA; uint8 x; GetZPI(EA,HU_Y); x=HU_Page1[EA]; op; break; }
#define LD_AB(op) { unsigned int EA; uint8 x; GetAB(EA); x=RdMem(EA); op; break; }
#define LD_ABI(reg,op) { unsigned int EA; uint8 x; GetABI(EA,reg); x=RdMem(EA); op; break; }
#define LD_ABX(op) LD_ABI(HU_X,op)
#define LD_ABY(op) LD_ABI(HU_Y,op)
#define LD_IND(op) { unsigned int EA; uint8 x; GetIND(EA); x=RdMem(EA); op; break; }
#define LD_IX(op) { unsigned int EA; uint8 x; GetIX(EA); x=RdMem(EA); op; break; }
#define LD_IY(op) { unsigned int EA; uint8 x; GetIY(EA); x=RdMem(EA); op; break; }
#define BMT_PREHONK(pork) HuCPU.in_block_move = IBM_##pork;
#define BMT_HONKHONK(pork) if(HuCPU.timestamp >= next_user_event) goto GetOutBMT; continue_the_##pork:
#define BMT_TDD BMT_PREHONK(TDD); do { ADDCYC(6); WrMem(HuCPU.bmt_dest, RdMem(HuCPU.bmt_src)); HuCPU.bmt_src--; HuCPU.bmt_dest--; BMT_HONKHONK(TDD); HuCPU.bmt_length--; } while(HuCPU.bmt_length);
#define BMT_TAI BMT_PREHONK(TAI); {HuCPU.bmt_alternate = 0; do { ADDCYC(6); WrMem(HuCPU.bmt_dest, RdMem(HuCPU.bmt_src + HuCPU.bmt_alternate)); HuCPU.bmt_dest++; HuCPU.bmt_alternate ^= 1; BMT_HONKHONK(TAI); HuCPU.bmt_length--; } while(HuCPU.bmt_length); }
#define BMT_TIA BMT_PREHONK(TIA); {HuCPU.bmt_alternate = 0; do { ADDCYC(6); WrMem(HuCPU.bmt_dest + HuCPU.bmt_alternate, RdMem(HuCPU.bmt_src)); HuCPU.bmt_src++; HuCPU.bmt_alternate ^= 1; BMT_HONKHONK(TIA); HuCPU.bmt_length--; } while(HuCPU.bmt_length); }
#define BMT_TII BMT_PREHONK(TII); do { ADDCYC(6); WrMem(HuCPU.bmt_dest, RdMem(HuCPU.bmt_src)); HuCPU.bmt_src++; HuCPU.bmt_dest++; BMT_HONKHONK(TII); HuCPU.bmt_length--; } while(HuCPU.bmt_length);
#define BMT_TIN BMT_PREHONK(TIN); do { ADDCYC(6); WrMem(HuCPU.bmt_dest, RdMem(HuCPU.bmt_src)); HuCPU.bmt_src++; BMT_HONKHONK(TIN); HuCPU.bmt_length--; } while(HuCPU.bmt_length);
// Block memory transfer load
#define LD_BMT(op) { PUSH(HU_Y); PUSH(HU_A); PUSH(HU_X); GetAB(HuCPU.bmt_src); GetAB(HuCPU.bmt_dest); GetAB(HuCPU.bmt_length); op; HuCPU.in_block_move = 0; HU_X = POP(); HU_A = POP(); HU_Y = POP(); break; }
#define ST_ZP(r) {uint8 EA; GetZP(EA); HU_Page1[EA] = r; break;}
#define ST_ZPX(r) {uint8 EA; GetZPI(EA,HU_X); HU_Page1[EA] = r; break;}
#define ST_ZPY(r) {uint8 EA; GetZPI(EA,HU_Y); HU_Page1[EA] = r; break;}
#define ST_AB(r) {unsigned int EA; GetAB(EA); WrMem(EA, r); break;}
#define ST_ABI(reg,r) {unsigned int EA; GetABI(EA,reg); WrMem(EA,r); break; }
#define ST_ABX(r) ST_ABI(HU_X,r)
#define ST_ABY(r) ST_ABI(HU_Y,r)
#define ST_IND(r) {unsigned int EA; GetIND(EA); WrMem(EA,r); break; }
#define ST_IX(r) {unsigned int EA; GetIX(EA); WrMem(EA,r); break; }
#define ST_IY(r) {unsigned int EA; GetIY(EA); WrMem(EA,r); break; }
static const uint8 CycTable[256] =
{
2015-07-25 02:21:22 +00:00
/*0x00*/ 8, 7, 3, 4, 6, 4, 6, 7, 3, 2, 2, 2, 7, 5, 7, 6,
/*0x10*/ 2, 7, 7, 4, 6, 4, 6, 7, 2, 5, 2, 2, 7, 5, 7, 6,
/*0x20*/ 7, 7, 3, 4, 4, 4, 6, 7, 4, 2, 2, 2, 5, 5, 7, 6,
/*0x30*/ 2, 7, 7, 2, 4, 4, 6, 7, 2, 5, 2, 2, 5, 5, 7, 6,
/*0x40*/ 7, 7, 3, 4, 8, 4, 6, 7, 3, 2, 2, 2, 4, 5, 7, 6,
/*0x50*/ 2, 7, 7, 5, 3, 4, 6, 7, 2, 5, 3, 2, 2, 5, 7, 6,
/*0x60*/ 7, 7, 2, 2, 4, 4, 6, 7, 4, 2, 2, 2, 7, 5, 7, 6,
/*0x70*/ 2, 7, 7, 17, 4, 4, 6, 7, 2, 5, 4, 2, 7, 5, 7, 6,
/*0x80*/ 4, 7, 2, 7, 4, 4, 4, 7, 2, 2, 2, 2, 5, 5, 5, 6,
/*0x90*/ 2, 7, 7, 8, 4, 4, 4, 7, 2, 5, 2, 2, 5, 5, 5, 6,
/*0xA0*/ 2, 7, 2, 7, 4, 4, 4, 7, 2, 2, 2, 2, 5, 5, 5, 6,
/*0xB0*/ 2, 7, 7, 8, 4, 4, 4, 7, 2, 5, 2, 2, 5, 5, 5, 6,
/*0xC0*/ 2, 7, 2, 17, 4, 4, 6, 7, 2, 2, 2, 2, 5, 5, 7, 6,
/*0xD0*/ 2, 7, 7, 17, 3, 4, 6, 7, 2, 5, 3, 2, 2, 5, 7, 6,
/*0xE0*/ 2, 7, 2, 17, 4, 4, 6, 7, 2, 2, 2, 2, 5, 5, 7, 6,
/*0xF0*/ 2, 7, 7, 17, 2, 4, 6, 7, 2, 5, 4, 2, 2, 5, 7, 6,
2013-01-16 14:22:03 +00:00
};
void HuC6280_Reset(void)
{
2020-10-04 14:43:04 +00:00
int i;
unsigned int npc;
2015-07-25 02:21:22 +00:00
HuCPU.timer_next_timestamp = HuCPU.timestamp + 1024;
2013-01-16 14:22:03 +00:00
2015-07-25 02:21:22 +00:00
HuCPU.timer_load = 0;
HuCPU.timer_value = 0;
HuCPU.timer_status = 0;
HuCPU.in_block_move = 0;
2013-01-16 14:22:03 +00:00
2015-07-25 02:21:22 +00:00
HuCPU.IRQMask = HuCPU.IRQMaskDelay = 7;
2013-01-16 14:22:03 +00:00
2015-07-25 02:21:22 +00:00
HuC6280_SetMPR(0, 0xFF);
HuC6280_SetMPR(8, 0xFF);
HuC6280_SetMPR(1, 0xF8);
2013-01-16 14:22:03 +00:00
2020-10-04 14:43:04 +00:00
for(i = 2; i < 8; i++)
2015-07-25 02:21:22 +00:00
HuC6280_SetMPR(i, 0);
2013-01-16 14:22:03 +00:00
2015-07-25 02:21:22 +00:00
npc = RdMem16(0xFFFE);
2013-01-16 14:22:03 +00:00
2015-07-25 02:21:22 +00:00
#define PC_local HuCPU.PC
SetPC(npc);
#undef PC_local
2013-01-16 14:22:03 +00:00
2015-07-25 02:21:22 +00:00
HuCPU.mooPI = I_FLAG;
HuCPU.P = I_FLAG;
2013-01-16 14:22:03 +00:00
2015-07-25 02:21:22 +00:00
HU_IRQlow = 0;
2013-01-16 14:22:03 +00:00
}
2015-07-25 02:21:22 +00:00
2013-01-16 14:22:03 +00:00
void HuC6280_Init(void)
{
2020-10-04 14:43:04 +00:00
int x;
unsigned i;
memset(&HuCPU,0,sizeof(HuCPU));
2013-01-16 14:22:03 +00:00
2015-07-25 02:21:22 +00:00
#ifdef HUC6280_LAZY_FLAGS
#else
2020-10-04 14:43:04 +00:00
for(x=0; x < 256; x++)
{
2015-07-25 02:21:22 +00:00
if(!x) ZNTable[x]=Z_FLAG;
else if (x&0x80) ZNTable[x]=N_FLAG;
else ZNTable[x]=0;
2020-10-04 14:43:04 +00:00
}
2015-07-25 02:21:22 +00:00
#endif
2020-10-04 14:43:04 +00:00
for (i = 0; i < 0x100; i++)
HuCPU.FastMap[i] = dummy_bank;
2013-01-16 14:22:03 +00:00
}
void HuC6280_Power(void)
{
2020-10-04 14:43:04 +00:00
int i;
memset(dummy_bank, 0, sizeof(dummy_bank));
2015-07-25 02:21:22 +00:00
HuCPU.IRQlow = 0;
2013-01-16 14:22:03 +00:00
2015-07-25 02:21:22 +00:00
HuCPU.A = 0;
HuCPU.X = 0;
HuCPU.Y = 0;
HuCPU.S = 0;
HuCPU.P = 0;
HuCPU.mooPI = 0;
2013-01-16 14:22:03 +00:00
2015-07-25 02:21:22 +00:00
HuCPU.PC = 0;
2013-01-16 14:22:03 +00:00
2015-07-25 02:21:22 +00:00
HuCPU.timestamp = 0;
2013-01-16 14:22:03 +00:00
2020-10-04 14:43:04 +00:00
for (i = 0; i < 9; i++)
2015-07-25 02:21:22 +00:00
{
HuCPU.MPR[i] = 0;
2020-10-04 14:43:04 +00:00
HuCPU.FastPageR[i] = 0;
2015-07-25 02:21:22 +00:00
}
HuC6280_Reset();
2013-01-16 14:22:03 +00:00
}
void HuC6280_Run(int32 cycles)
{
2020-10-04 14:43:04 +00:00
int i;
int32 next_event;
2015-07-25 02:21:22 +00:00
const int32 next_user_event = HuCPU.previous_next_user_event + cycles * pce_overclocked;
HuCPU.previous_next_user_event = next_user_event;
{
2020-10-04 14:43:04 +00:00
#ifdef HUC6280_CRAZY_VERSION
uintptr_t PC_local = HuCPU.PC;
#else
uint32 PC_local = HuCPU.PC;
#endif
uint8 X_local = HuCPU.X;
uint8 Y_local = HuCPU.Y;
uint8 P_local = HuCPU.P;
uint8 *Page1_local = HuCPU.Page1;
2015-07-25 02:21:22 +00:00
2020-10-04 14:43:04 +00:00
if(HuCPU.timestamp >= next_user_event)
return;
if(HuCPU.in_block_move)
2015-07-25 02:21:22 +00:00
{
2020-10-04 14:43:04 +00:00
next_event = (next_user_event < HuCPU.timer_next_timestamp) ? next_user_event : HuCPU.timer_next_timestamp;
2015-07-25 02:21:22 +00:00
2020-10-04 14:43:04 +00:00
switch(HuCPU.in_block_move)
{
case IBM_TIA: goto continue_the_TIA;
case IBM_TAI: goto continue_the_TAI;
case IBM_TDD: goto continue_the_TDD;
case IBM_TII: goto continue_the_TII;
case IBM_TIN: goto continue_the_TIN;
}
}
2015-07-25 02:21:22 +00:00
2020-10-04 14:43:04 +00:00
while(MDFN_LIKELY(HuCPU.timestamp < next_user_event))
2015-07-25 02:21:22 +00:00
{
2020-10-04 14:43:04 +00:00
next_event = (next_user_event < HuCPU.timer_next_timestamp) ? next_user_event : HuCPU.timer_next_timestamp;
2015-07-25 02:21:22 +00:00
2020-10-04 14:43:04 +00:00
while(MDFN_LIKELY(HuCPU.timestamp < next_event))
2015-07-25 02:21:22 +00:00
{
2020-10-04 14:43:04 +00:00
uint8 b1;
if(HU_IRQlow)
2015-07-25 02:21:22 +00:00
{
2020-10-04 14:43:04 +00:00
if(!(HU_PI&I_FLAG))
{
uint32 tmpa = 0;
2015-07-25 02:21:22 +00:00
2020-10-04 14:43:04 +00:00
if(HU_IRQlow & MDFN_IQTIMER & HuCPU.IRQMaskDelay)
tmpa = 0xFFFA;
else if((HU_IRQlow & MDFN_IQIRQ1 & HuCPU.IRQMaskDelay) || ((HU_IRQlow >> 8) & MDFN_IQIRQ1 & HuCPU.IRQMaskDelay))
tmpa = 0xFFF8;
else if(HU_IRQlow & MDFN_IQIRQ2 & HuCPU.IRQMaskDelay)
tmpa = 0xFFF6;
2015-07-25 02:21:22 +00:00
2020-10-04 14:43:04 +00:00
if(tmpa)
{
unsigned int npc;
2015-07-25 02:21:22 +00:00
2020-10-04 14:43:04 +00:00
ADDCYC(8);
PUSH_PC();
2015-07-25 02:21:22 +00:00
2020-10-04 14:43:04 +00:00
COMPRESS_FLAGS();
PUSH((HU_P&~B_FLAG));
HU_P |= I_FLAG;
HU_P &= ~(T_FLAG | D_FLAG);
HU_PI = HU_P;
2015-07-25 02:21:22 +00:00
2020-10-04 14:43:04 +00:00
npc = RdMem16(tmpa);
SetPC(npc);
2015-07-25 02:21:22 +00:00
2020-10-04 14:43:04 +00:00
if(tmpa == 0xFFF8)
HU_IRQlow &= ~0x200;
2015-07-25 02:21:22 +00:00
2020-10-04 14:43:04 +00:00
continue;
}
2015-07-25 02:21:22 +00:00
}
2020-10-04 14:43:04 +00:00
} // end if(HU_IRQlow)
2015-07-25 02:21:22 +00:00
2020-10-04 14:43:04 +00:00
HU_PI = HU_P;
HuCPU.IRQMaskDelay = HuCPU.IRQMask;
2015-07-25 02:21:22 +00:00
2020-10-04 14:43:04 +00:00
b1 = RdAtPC();
2015-07-25 02:21:22 +00:00
2020-10-04 14:43:04 +00:00
ADDCYC(CycTable[b1]);
2015-07-25 02:21:22 +00:00
2020-10-04 14:43:04 +00:00
IncPC();
2015-07-25 02:21:22 +00:00
2020-10-04 14:43:04 +00:00
switch(b1)
{
2020-10-06 13:53:09 +00:00
#include "huc6280_ops.h"
2020-10-04 14:43:04 +00:00
}
2015-07-25 02:21:22 +00:00
#ifndef HUC6280_EXTRA_CRAZY
2020-10-04 14:43:04 +00:00
FixPC_PC();
2015-07-25 02:21:22 +00:00
#endif
2020-10-04 14:43:04 +00:00
} // end while(HuCPU.timestamp < next_event)
2015-07-25 02:21:22 +00:00
2020-10-04 14:43:04 +00:00
while(HuCPU.timestamp >= HuCPU.timer_next_timestamp)
2015-07-25 02:21:22 +00:00
{
2020-10-04 14:43:04 +00:00
HuCPU.timer_next_timestamp += 1024 * pce_overclocked;
if(HuCPU.timer_status)
2015-07-25 02:21:22 +00:00
{
2020-10-04 14:43:04 +00:00
HuCPU.timer_value --;
if(HuCPU.timer_value < 0)
{
HuCPU.timer_value = HuCPU.timer_load;
HuC6280_IRQBegin(MDFN_IQTIMER);
}
2015-07-25 02:21:22 +00:00
}
2013-01-16 14:22:03 +00:00
}
2020-10-04 14:43:04 +00:00
} // end while(HuCPU.timestamp < next_user_event)
2013-01-16 14:22:03 +00:00
2015-07-25 02:21:22 +00:00
GetOutBMT:
2013-01-16 14:22:03 +00:00
2020-10-04 14:43:04 +00:00
SAVE_LOCALS();
}
2013-01-16 14:22:03 +00:00
}
void HuC6280_ResetTS(void)
{
2015-07-25 02:21:22 +00:00
HuCPU.timer_next_timestamp -= HuCPU.timestamp;
HuCPU.previous_next_user_event -= HuCPU.timestamp;
HuCPU.timestamp = 0;
2013-01-16 14:22:03 +00:00
}
int HuC6280_StateAction(StateMem *sm, int load, int data_only)
{
2020-10-04 14:43:04 +00:00
int ret;
2015-07-25 02:21:22 +00:00
uint16 tmp_PC = GetRealPC_EXTERNAL();
#define P_local HuCPU.P
COMPRESS_FLAGS();
{
2020-10-04 14:43:04 +00:00
SFORMAT SFCPU[]=
{
SFVARN(tmp_PC, "PC"),
SFVARN(HuCPU.A, "A"),
SFVARN(HuCPU.P, "P"),
SFVARN(HuCPU.X, "X"),
SFVARN(HuCPU.Y, "Y"),
SFVARN(HuCPU.S, "S"),
SFVARN(HuCPU.mooPI, "PI"),
SFVARN(HuCPU.IRQMask, "IRQMask"),
SFVARN(HuCPU.IRQMaskDelay, "IRQMaskDelay"),
SFARRAYN(HuCPU.MPR, 8, "MPR"),
SFVARN(HuCPU.timer_status, "timer_status"),
SFVARN(HuCPU.timer_value, "timer_value"),
SFVARN(HuCPU.timer_load, "timer_load"),
SFVARN(HuCPU.IRQlow, "IRQlow"),
SFVARN(HuCPU.in_block_move, "IBM"),
SFVARN(HuCPU.bmt_src, "IBM_SRC"),
SFVARN(HuCPU.bmt_dest, "IBM_DEST"),
SFVARN(HuCPU.bmt_length, "IBM_LENGTH"),
SFVARN(HuCPU.bmt_alternate, "IBM_ALTERNATE"),
SFVARN(HuCPU.timestamp, "timestamp"),
SFVARN(HuCPU.timer_next_timestamp, "timer_next_timestamp"),
SFVARN(HuCPU.previous_next_user_event, "previous_next_user_event"),
SFEND
};
ret = MDFNSS_StateAction(sm, load, data_only, SFCPU, "CPU", false);
if(load)
{
// Update MPR cache
HuC6280_FlushMPRCache();
2015-07-25 02:21:22 +00:00
2020-10-04 14:43:04 +00:00
// This must be after the MPR cache is updated:
SetPC_EXTERNAL(tmp_PC);
}
2015-07-25 02:21:22 +00:00
2020-10-04 14:43:04 +00:00
EXPAND_FLAGS();
2015-07-25 02:21:22 +00:00
#undef P_local
2020-10-04 14:43:04 +00:00
}
2015-07-25 02:21:22 +00:00
return(ret);
2013-01-16 14:22:03 +00:00
}