📄 tms34010.c
字号:
/*** TMS34010: Portable Texas Instruments TMS34010 emulator **************
Copyright (C) Alex Pasadyn/Zsolt Vasvari 1998
Parts based on code by Aaron Giles
*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include "osd_cpu.h"
#include "tms34010.h"
#include "34010ops.h"
#include "driver.h"
#ifdef MAME_DEBUG
extern int debug_key_pressed;
#endif
/* For now, define the master processor to be CPU #0, the slave to be #1 */
#define CPU_MASTER 0
#define CPU_SLAVE 1
static TMS34010_Regs state;
static int *TMS34010_timer[MAX_CPU]; /* Display interrupt timer */
static UINT8* stackbase[MAX_CPU] = {0,0,0,0};
static UINT32 stackoffs[MAX_CPU] = {0,0,0,0};
static void (*to_shiftreg [MAX_CPU])(UINT32, UINT16*) = {0,0,0,0};
static void (*from_shiftreg[MAX_CPU])(UINT32, UINT16*) = {0,0,0,0};
static void TMS34010_io_intcallback(int param);
static void (*wfield_functions[32]) (UINT32 bitaddr, UINT32 data) =
{
wfield_32, wfield_01, wfield_02, wfield_03, wfield_04, wfield_05,
wfield_06, wfield_07, wfield_08, wfield_09, wfield_10, wfield_11,
wfield_12, wfield_13, wfield_14, wfield_15, wfield_16, wfield_17,
wfield_18, wfield_19, wfield_20, wfield_21, wfield_22, wfield_23,
wfield_24, wfield_25, wfield_26, wfield_27, wfield_28, wfield_29,
wfield_30, wfield_31
};
static INT32 (*rfield_functions_z[32]) (UINT32 bitaddr) =
{
rfield_32 , rfield_z_01, rfield_z_02, rfield_z_03, rfield_z_04, rfield_z_05,
rfield_z_06, rfield_z_07, rfield_z_08, rfield_z_09, rfield_z_10, rfield_z_11,
rfield_z_12, rfield_z_13, rfield_z_14, rfield_z_15, rfield_z_16, rfield_z_17,
rfield_z_18, rfield_z_19, rfield_z_20, rfield_z_21, rfield_z_22, rfield_z_23,
rfield_z_24, rfield_z_25, rfield_z_26, rfield_z_27, rfield_z_28, rfield_z_29,
rfield_z_30, rfield_z_31
};
static INT32 (*rfield_functions_s[32]) (UINT32 bitaddr) =
{
rfield_32 , rfield_s_01, rfield_s_02, rfield_s_03, rfield_s_04, rfield_s_05,
rfield_s_06, rfield_s_07, rfield_s_08, rfield_s_09, rfield_s_10, rfield_s_11,
rfield_s_12, rfield_s_13, rfield_s_14, rfield_s_15, rfield_s_16, rfield_s_17,
rfield_s_18, rfield_s_19, rfield_s_20, rfield_s_21, rfield_s_22, rfield_s_23,
rfield_s_24, rfield_s_25, rfield_s_26, rfield_s_27, rfield_s_28, rfield_s_29,
rfield_s_30, rfield_s_31
};
/* public globals */
int TMS34010_ICount;
/* register definitions and shortcuts */
#define PC (state.pc)
#define N_FLAG (state.nflag)
#define NOTZ_FLAG (state.notzflag)
#define C_FLAG (state.cflag)
#define V_FLAG (state.vflag)
#define P_FLAG (state.pflag)
#define IE_FLAG (state.ieflag)
#define FE0_FLAG (state.fe0flag)
#define FE1_FLAG (state.fe1flag)
#define AREG(i) (state.regs.a.Aregs[i])
#define BREG(i) (state.regs.Bregs[i])
#define SP (state.regs.a.Aregs[15])
#define FW(i) (state.fw[i])
#define FW_INC(i) (state.fw_inc[i])
#define ASRCREG (((state.op)>>5)&0x0f)
#define ADSTREG ((state.op) &0x0f)
#define BSRCREG (((state.op)&0x1e0)>>1)
#define BDSTREG (((state.op)&0x0f)<<4)
#define SKIP_WORD (PC += (2<<3))
#define SKIP_LONG (PC += (4<<3))
#define PARAM_K (((state.op)>>5)&0x1f)
#define PARAM_N ((state.op)&0x1f)
#define PARAM_REL8 ((signed char) ((state.op)&0x00ff))
#define WFIELD0(a,b) state.F0_write(a,b)
#define WFIELD1(a,b) state.F1_write(a,b)
#define RFIELD0(a) state.F0_read(a)
#define RFIELD1(a) state.F1_read(a)
#define WPIXEL(a,b) state.pixel_write(a,b)
#define RPIXEL(a) state.pixel_read(a)
/* Implied Operands */
#define SADDR BREG(0<<4)
#define SPTCH BREG(1<<4)
#define DADDR BREG(2<<4)
#define DPTCH BREG(3<<4)
#define OFFSET BREG(4<<4)
#define WSTART BREG(5<<4)
#define WEND BREG(6<<4)
#define DYDX BREG(7<<4)
#define COLOR0 BREG(8<<4)
#define COLOR1 BREG(9<<4)
#define COUNT BREG(10<<4)
#define INC1 BREG(11<<4)
#define INC2 BREG(12<<4)
#define PATTRN BREG(13<<4)
#define TEMP BREG(14<<4)
/* set the field widths - shortcut */
INLINE void SET_FW(void)
{
FW_INC(0) = (FW(0) ? FW(0) : 0x20);
FW_INC(1) = (FW(1) ? FW(1) : 0x20);
state.F0_write = wfield_functions[FW(0)];
state.F1_write = wfield_functions[FW(1)];
if (FE0_FLAG)
{
state.F0_read = rfield_functions_s[FW(0)]; /* Sign extend */
}
else
{
state.F0_read = rfield_functions_z[FW(0)]; /* Zero extend */
}
if (FE1_FLAG)
{
state.F1_read = rfield_functions_s[FW(1)]; /* Sign extend */
}
else
{
state.F1_read = rfield_functions_z[FW(1)]; /* Zero extend */
}
}
/* Intialize Status to 0x0010 */
INLINE void RESET_ST(void)
{
N_FLAG = C_FLAG = V_FLAG = P_FLAG = IE_FLAG = FE0_FLAG = FE1_FLAG = 0;
NOTZ_FLAG = 1;
FW(0) = 0x10;
FW(1) = 0;
SET_FW();
}
/* Combine indiviual flags into the Status Register */
INLINE UINT32 GET_ST(void)
{
return ( N_FLAG ? 0x80000000 : 0) |
( C_FLAG ? 0x40000000 : 0) |
( NOTZ_FLAG ? 0 : 0x20000000) |
( V_FLAG ? 0x10000000 : 0) |
( P_FLAG ? 0x02000000 : 0) |
( IE_FLAG ? 0x00200000 : 0) |
( FE0_FLAG ? 0x00000020 : 0) |
( FE1_FLAG ? 0x00000800 : 0) |
FW(0) |
(FW(1) << 6);
}
/* Break up Status Register into indiviual flags */
INLINE void SET_ST(UINT32 st)
{
N_FLAG = st & 0x80000000;
C_FLAG = st & 0x40000000;
NOTZ_FLAG = !(st & 0x20000000);
V_FLAG = st & 0x10000000;
P_FLAG = st & 0x02000000;
IE_FLAG = st & 0x00200000;
FE0_FLAG = st & 0x00000020;
FE1_FLAG = st & 0x00000800;
FW(0) = st & 0x1f;
FW(1) = (st >> 6) & 0x1f;
SET_FW();
}
/* shortcuts for reading opcodes */
INLINE UINT32 ROPCODE (void)
{
UINT32 pc = TOBYTE(PC);
PC += (2<<3);
return cpu_readop16(pc);
}
INLINE INT16 PARAM_WORD (void)
{
UINT32 pc = TOBYTE(PC);
PC += (2<<3);
return cpu_readop_arg16(pc);
}
INLINE INT16 PARAM_WORD_NO_INC (void)
{
return cpu_readop_arg16(TOBYTE(PC));
}
INLINE INT32 PARAM_LONG_NO_INC (void)
{
UINT32 pc = TOBYTE(PC);
return cpu_readop_arg16(pc) | ((UINT32)(UINT16)cpu_readop_arg16(pc+2) << 16);
}
INLINE INT32 PARAM_LONG (void)
{
INT32 ret = PARAM_LONG_NO_INC();
PC += (4<<3);
return ret;
}
/* read memory byte */
INLINE INT8 RBYTE (UINT32 bitaddr)
{
RFIELDMAC_Z_8;
}
/* write memory byte */
INLINE void WBYTE (UINT32 bitaddr, UINT32 data)
{
WFIELDMAC_8;
}
/* read memory long */
INLINE INT32 RLONG (UINT32 bitaddr)
{
RFIELDMAC_32;
}
/* write memory long */
INLINE void WLONG (UINT32 bitaddr, UINT32 data)
{
WFIELDMAC_32;
}
/* pushes/pops a value from the stack
These are called millions of times. If you change it, please test effect
on performance */
INLINE void PUSH (UINT32 data)
{
UINT8* base;
SP -= 0x20;
base = STACKPTR(SP);
WRITE_WORD(base, (UINT16)data);
WRITE_WORD(base+2, data >> 16);
}
INLINE INT32 POP (void)
{
UINT8* base = STACKPTR(SP);
INT32 ret = READ_WORD(base) + (READ_WORD(base+2) << 16);
SP += 0x20;
return ret;
}
/* No Raster Op + No Transparency */
#define WP(m1,m2) \
UINT32 boundary = 0; \
UINT32 a = TOBYTE(address&0xfffffff0); \
UINT32 shiftcount = (address&m1); \
if (state.lastpixaddr != a) \
{ \
if (state.lastpixaddr != INVALID_PIX_ADDRESS) \
{ \
TMS34010_WRMEM_WORD(state.lastpixaddr, state.lastpixword); \
boundary = 1; \
} \
state.lastpixword = TMS34010_RDMEM_WORD(a); \
state.lastpixaddr = a; \
} \
\
/* TODO: plane masking */ \
\
value &= m2; \
state.lastpixword = (state.lastpixword & ~(m2<<shiftcount)) | (value<<shiftcount); \
\
return boundary;
/* No Raster Op + Transparency */
#define WP_T(m1,m2) \
UINT32 boundary = 0; \
UINT32 a = TOBYTE(address&0xfffffff0); \
if (state.lastpixaddr != a) \
{ \
if (state.lastpixaddr != INVALID_PIX_ADDRESS) \
{ \
if (state.lastpixwordchanged) \
{ \
TMS34010_WRMEM_WORD(state.lastpixaddr, state.lastpixword); \
} \
boundary = 1; \
} \
state.lastpixword = TMS34010_RDMEM_WORD(a); \
state.lastpixaddr = a; \
state.lastpixwordchanged = 0; \
} \
\
/* TODO: plane masking */ \
\
value &= m2; \
if (value) \
{ \
UINT32 shiftcount = (address&m1); \
state.lastpixword = (state.lastpixword & ~(m2<<shiftcount)) | (value<<shiftcount); \
state.lastpixwordchanged = 1; \
} \
\
return boundary;
/* Raster Op + No Transparency */
#define WP_R(m1,m2) \
UINT32 oldpix; \
UINT32 boundary = 0; \
UINT32 a = TOBYTE(address&0xfffffff0); \
UINT32 shiftcount = (address&m1); \
if (state.lastpixaddr != a) \
{ \
if (state.lastpixaddr != INVALID_PIX_ADDRESS) \
{ \
TMS34010_WRMEM_WORD(state.lastpixaddr, state.lastpixword); \
boundary = 1; \
} \
state.lastpixword = TMS34010_RDMEM_WORD(a); \
state.lastpixaddr = a; \
} \
\
/* TODO: plane masking */ \
\
oldpix = (state.lastpixword >> shiftcount) & m2; \
value = state.raster_op(value & m2, oldpix) & m2; \
\
state.lastpixword = (state.lastpixword & ~(m2<<shiftcount)) | (value<<shiftcount); \
\
return boundary;
/* Raster Op + Transparency */
#define WP_R_T(m1,m2) \
UINT32 oldpix; \
UINT32 boundary = 0; \
UINT32 a = TOBYTE(address&0xfffffff0); \
UINT32 shiftcount = (address&m1); \
if (state.lastpixaddr != a) \
{ \
if (state.lastpixaddr != INVALID_PIX_ADDRESS) \
{ \
if (state.lastpixwordchanged) \
{ \
TMS34010_WRMEM_WORD(state.lastpixaddr, state.lastpixword); \
} \
boundary = 1; \
} \
state.lastpixword = TMS34010_RDMEM_WORD(a); \
state.lastpixaddr = a; \
state.lastpixwordchanged = 0; \
} \
\
/* TODO: plane masking */ \
\
oldpix = (state.lastpixword >> shiftcount) & m2; \
value = state.raster_op(value & m2, oldpix) & m2; \
\
if (value) \
{ \
state.lastpixword = (state.lastpixword & ~(m2<<shiftcount)) | (value<<shiftcount); \
state.lastpixwordchanged = 1; \
} \
\
return boundary;
/* These functions return 'true' on word boundary, 'false' otherwise */
/* No Raster Op + No Transparency */
static UINT32 write_pixel_1 (UINT32 address, UINT32 value) { WP(0x0f,0x01); }
static UINT32 write_pixel_2 (UINT32 address, UINT32 value) { WP(0x0e,0x03); }
static UINT32 write_pixel_4 (UINT32 address, UINT32 value) { WP(0x0c,0x0f); }
static UINT32 write_pixel_8 (UINT32 address, UINT32 value) { WP(0x08,0xff); }
static UINT32 write_pixel_16(UINT32 address, UINT32 value)
{
TMS34010_WRMEM_WORD(TOBYTE(address&0xfffffff0), value);
return 1;
}
/* No Raster Op + Transparency */
static UINT32 write_pixel_t_1 (UINT32 address, UINT32 value) { WP_T(0x0f,0x01); }
static UINT32 write_pixel_t_2 (UINT32 address, UINT32 value) { WP_T(0x0e,0x03); }
static UINT32 write_pixel_t_4 (UINT32 address, UINT32 value) { WP_T(0x0c,0x0f); }
static UINT32 write_pixel_t_8 (UINT32 address, UINT32 value) { WP_T(0x08,0xff); }
static UINT32 write_pixel_t_16(UINT32 address, UINT32 value)
{
if (value)
{
TMS34010_WRMEM_WORD(TOBYTE(address&0xfffffff0), value);
}
return 1;
}
/* Raster Op + No Transparency */
static UINT32 write_pixel_r_1 (UINT32 address, UINT32 value) { WP_R(0x0f,0x01); }
static UINT32 write_pixel_r_2 (UINT32 address, UINT32 value) { WP_R(0x0e,0x03); }
static UINT32 write_pixel_r_4 (UINT32 address, UINT32 value) { WP_R(0x0c,0x0f); }
static UINT32 write_pixel_r_8 (UINT32 address, UINT32 value) { WP_R(0x08,0xff); }
static UINT32 write_pixel_r_16(UINT32 address, UINT32 value)
{
UINT32 a = TOBYTE(address&0xfffffff0);
TMS34010_WRMEM_WORD(a, state.raster_op(value, TMS34010_RDMEM_WORD(a)));
return 1;
}
/* Raster Op + Transparency */
static UINT32 write_pixel_r_t_1 (UINT32 address, UINT32 value) { WP_R_T(0x0f,0x01); }
static UINT32 write_pixel_r_t_2 (UINT32 address, UINT32 value) { WP_R_T(0x0e,0x03); }
static UINT32 write_pixel_r_t_4 (UINT32 address, UINT32 value) { WP_R_T(0x0c,0x0f); }
static UINT32 write_pixel_r_t_8 (UINT32 address, UINT32 value) { WP_R_T(0x08,0xff); }
static UINT32 write_pixel_r_t_16(UINT32 address, UINT32 value)
{
UINT32 a = TOBYTE(address&0xfffffff0);
value = state.raster_op(value, TMS34010_RDMEM_WORD(a));
if (value)
{
TMS34010_WRMEM_WORD(a, value);
}
return 1;
}
#define RP(m1,m2) \
/* TODO: Plane masking */ \
return (TMS34010_RDMEM_WORD(TOBYTE(address&0xfffffff0)) >> (address&m1)) & m2;
static UINT32 read_pixel_1 (UINT32 address) { RP(0x0f,0x01) }
static UINT32 read_pixel_2 (UINT32 address) { RP(0x0e,0x03) }
static UINT32 read_pixel_4 (UINT32 address) { RP(0x0c,0x0f) }
static UINT32 read_pixel_8 (UINT32 address) { RP(0x08,0xff) }
static UINT32 read_pixel_16(UINT32 address)
{
return TMS34010_RDMEM_WORD(TOBYTE(address&0xfffffff0));
}
#define FINISH_PIX_OP \
if (state.lastpixaddr != INVALID_PIX_ADDRESS) \
{ \
TMS34010_WRMEM_WORD(state.lastpixaddr, state.lastpixword); \
} \
state.lastpixaddr = INVALID_PIX_ADDRESS; \
P_FLAG = 0;
static UINT32 write_pixel_shiftreg (UINT32 address, UINT32 value)
{
if (state.from_shiftreg)
{
state.from_shiftreg(address, &state.shiftreg[0]);
}
return 1;
}
static UINT32 read_pixel_shiftreg (UINT32 address)
{
if (state.to_shiftreg)
{
state.to_shiftreg(address, &state.shiftreg[0]);
}
return state.shiftreg[0];
}
/* includes the static function prototypes and the master opcode table */
#include "34010tbl.c"
/* includes the actual opcode implementations */
#include "34010ops.c"
/* Raster operations */
static INT32 raster_op_1(INT32 newpix, INT32 oldpix)
{
/* S AND D -> D */
return newpix & oldpix;
}
static INT32 raster_op_2(INT32 newpix, INT32 oldpix)
{
/* S AND ~D -> D */
return newpix & ~oldpix;
}
static INT32 raster_op_3(INT32 newpix, INT32 oldpix)
{
/* 0 -> D */
return 0;
}
static INT32 raster_op_4(INT32 newpix, INT32 oldpix)
{
/* S OR ~D -> D */
return newpix | ~oldpix;
}
static INT32 raster_op_5(INT32 newpix, INT32 oldpix)
{
/* FIXME!!! Not sure about this one? */
/* S XNOR D -> D */
return ~(newpix ^ oldpix);
}
static INT32 raster_op_6(INT32 newpix, INT32 oldpix)
{
/* ~D -> D */
return ~oldpix;
}
static INT32 raster_op_7(INT32 newpix, INT32 oldpix)
{
/* S NOR D -> D */
return ~(newpix | oldpix);
}
static INT32 raster_op_8(INT32 newpix, INT32 oldpix)
{
/* S OR D -> D */
return newpix | oldpix;
}
static INT32 raster_op_9(INT32 newpix, INT32 oldpix)
{
/* D -> D */
return oldpix;
}
static INT32 raster_op_10(INT32 newpix, INT32 oldpix)
{
/* S XOR D -> D */
return newpix ^ oldpix;
}
static INT32 raster_op_11(INT32 newpix, INT32 oldpix)
{
/* ~S AND D -> D */
return ~newpix & oldpix;
}
static INT32 raster_op_12(INT32 newpix, INT32 oldpix)
{
/* 1 -> D */
return 0xffff;
}
static INT32 raster_op_13(INT32 newpix, INT32 oldpix)
{
/* ~S OR D -> D */
return ~newpix | oldpix;
}
static INT32 raster_op_14(INT32 newpix, INT32 oldpix)
{
/* S NAND D -> D */
return ~(newpix & oldpix);
}
static INT32 raster_op_15(INT32 newpix, INT32 oldpix)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -