fixed C89 remaining incompatibilities + various code cleanup

This commit is contained in:
ekeeke31 2012-01-15 19:59:13 +00:00
parent 238382d8a8
commit 09c02fd693
35 changed files with 780 additions and 762 deletions

View File

@ -59,20 +59,23 @@ static void ar_write_ram_8(uint32 address, uint32 data);
void areplay_init(void) void areplay_init(void)
{ {
int size;
FILE *f;
memset(&action_replay,0,sizeof(action_replay)); memset(&action_replay,0,sizeof(action_replay));
if (cart.romsize > 0x800000) return;
/* store Action replay ROM (max. 128k) & RAM (64k) above cartridge ROM + SRAM area */
if (cart.romsize > 0x600000) return;
action_replay.rom = cart.rom + 0x600000;
action_replay.ram = cart.rom + 0x620000;
/* Open Action Replay ROM */ /* Open Action Replay ROM */
FILE *f = fopen(AR_ROM,"rb"); f = fopen(AR_ROM,"rb");
if (!f) return; if (f == NULL) return;
/* store Action replay ROM + RAM above cartridge ROM + SRAM */
action_replay.rom = cart.rom + 0x800000;
action_replay.ram = cart.rom + 0x810000;
/* ROM size */ /* ROM size */
fseek(f, 0, SEEK_END); fseek(f, 0, SEEK_END);
int size = ftell(f); size = ftell(f);
fseek(f, 0, SEEK_SET); fseek(f, 0, SEEK_SET);
/* detect Action Replay board type */ /* detect Action Replay board type */
@ -85,7 +88,6 @@ void areplay_init(void)
/* internal registers mapped at $010000-$01ffff */ /* internal registers mapped at $010000-$01ffff */
m68k_memory_map[0x01].write16 = ar_write_regs; m68k_memory_map[0x01].write16 = ar_write_regs;
break; break;
} }
@ -124,7 +126,6 @@ void areplay_init(void)
m68k_memory_map[sp[1]].write8 = ar_write_ram_8; m68k_memory_map[sp[1]].write8 = ar_write_ram_8;
m68k_memory_map[sp[1]].write16 = NULL; m68k_memory_map[sp[1]].write16 = NULL;
} }
break; break;
} }
@ -138,24 +139,23 @@ void areplay_init(void)
{ {
/* Load ROM */ /* Load ROM */
int i = 0; int i = 0;
while (i < size) for (i=0; i<size; i+=0x1000)
{ {
fread(action_replay.rom+i,0x1000,1,f); fread(action_replay.rom + i, 0x1000, 1, f);
i += 0x1000;
} }
#ifdef LSB_FIRST #ifdef LSB_FIRST
/* Byteswap ROM */ for (i= 0; i<size; i+=2)
uint8 temp;
for(i = 0; i < size; i += 2)
{ {
temp = action_replay.rom[i]; /* Byteswap ROM */
uint8 temp = action_replay.rom[i];
action_replay.rom[i] = action_replay.rom[i+1]; action_replay.rom[i] = action_replay.rom[i+1];
action_replay.rom[i+1] = temp; action_replay.rom[i+1] = temp;
} }
#endif #endif
} }
/* Close ROM file */
fclose(f); fclose(f);
} }

View File

@ -45,7 +45,7 @@ typedef enum
WAIT_START, WAIT_START,
GET_OPCODE, GET_OPCODE,
WRITE_WORD, WRITE_WORD,
READ_WORD, READ_WORD
} T_STATE; } T_STATE;

View File

@ -59,45 +59,40 @@ static void ggenie_write_regs(unsigned int offset, unsigned int data);
void ggenie_init(void) void ggenie_init(void)
{ {
int i;
FILE *f;
memset(&ggenie,0,sizeof(ggenie)); memset(&ggenie,0,sizeof(ggenie));
/* Open Game Genie ROM file */ /* Store Game Genie ROM (32k) above cartridge ROM + SRAM area */
FILE *f = fopen(GG_ROM,"rb"); if (cart.romsize > 0x600000) return;
if (!f) return;
/* Store Game Genie ROM above cartridge ROM + SRAM */
if (cart.romsize > 0x600000)
{
fclose(f);
return;
}
ggenie.rom = cart.rom + 0x600000; ggenie.rom = cart.rom + 0x600000;
/* Open Game Genie ROM file */
f = fopen(GG_ROM,"rb");
if (f == NULL) return;
/* Load ROM */ /* Load ROM */
int i = 0; for (i=0; i<0x8000; i+=0x1000)
while (i < 0x8000)
{ {
fread(ggenie.rom+i,0x1000,1,f); fread(ggenie.rom + i, 0x1000, 1, f);
i += 0x1000;
} }
/* Close ROM file */ /* Close ROM file */
fclose(f); fclose(f);
#ifdef LSB_FIRST #ifdef LSB_FIRST
/* Byteswap ROM */ for (i=0; i<0x8000; i+=2)
uint8 temp;
for(i = 0; i < 0x8000; i += 2)
{ {
temp = ggenie.rom[i]; /* Byteswap ROM */
uint8 temp = ggenie.rom[i];
ggenie.rom[i] = ggenie.rom[i+1]; ggenie.rom[i] = ggenie.rom[i+1];
ggenie.rom[i+1] = temp; ggenie.rom[i+1] = temp;
} }
#endif #endif
/* $0000-$7fff mirrored into $8000-$ffff */ /* $0000-$7fff mirrored into $8000-$ffff */
memcpy(ggenie.rom+0x8000,ggenie.rom,0x8000); memcpy(ggenie.rom + 0x8000, ggenie.rom, 0x8000);
/* set flag */ /* set flag */
ggenie.enabled = 1; ggenie.enabled = 1;

View File

@ -230,7 +230,7 @@ void md_eeprom_write_word(unsigned int address, unsigned int data)
} }
static inline void Detect_START() static __inline__ void Detect_START()
{ {
if (md_eeprom.old_scl && md_eeprom.scl) if (md_eeprom.old_scl && md_eeprom.scl)
{ {
@ -248,7 +248,7 @@ static inline void Detect_START()
} }
} }
static inline void Detect_STOP() static __inline__ void Detect_STOP()
{ {
if (md_eeprom.old_scl && md_eeprom.scl) if (md_eeprom.old_scl && md_eeprom.scl)
{ {

View File

@ -48,7 +48,7 @@ typedef enum
GET_WORD_ADR_HIGH, GET_WORD_ADR_HIGH,
GET_WORD_ADR_LOW, GET_WORD_ADR_LOW,
WRITE_DATA, WRITE_DATA,
READ_DATA, READ_DATA
} T_EEPROM_STATE; } T_EEPROM_STATE;

View File

@ -194,27 +194,27 @@
#define u32 unsigned int #define u32 unsigned int
//#define USE_DEBUGGER /*#define USE_DEBUGGER*/
// 0 /* 0 */
#define rX ssp->gr[SSP_X].h #define rX ssp->gr[SSP_X].byte.h
#define rY ssp->gr[SSP_Y].h #define rY ssp->gr[SSP_Y].byte.h
#define rA ssp->gr[SSP_A].h #define rA ssp->gr[SSP_A].byte.h
#define rST ssp->gr[SSP_ST].h // 4 #define rST ssp->gr[SSP_ST].byte.h /* 4 */
#define rSTACK ssp->gr[SSP_STACK].h #define rSTACK ssp->gr[SSP_STACK].byte.h
#define rPC ssp->gr[SSP_PC].h #define rPC ssp->gr[SSP_PC].byte.h
#define rP ssp->gr[SSP_P] #define rP ssp->gr[SSP_P]
#define rPM0 ssp->gr[SSP_PM0].h // 8 #define rPM0 ssp->gr[SSP_PM0].byte.h /* 8 */
#define rPM1 ssp->gr[SSP_PM1].h #define rPM1 ssp->gr[SSP_PM1].byte.h
#define rPM2 ssp->gr[SSP_PM2].h #define rPM2 ssp->gr[SSP_PM2].byte.h
#define rXST ssp->gr[SSP_XST].h #define rXST ssp->gr[SSP_XST].byte.h
#define rPM4 ssp->gr[SSP_PM4].h // 12 #define rPM4 ssp->gr[SSP_PM4].byte.h /* 12 */
// 13 /* 13 */
#define rPMC ssp->gr[SSP_PMC] // will keep addr in .h, mode in .l #define rPMC ssp->gr[SSP_PMC] /* will keep addr in .h, mode in .l */
#define rAL ssp->gr[SSP_A].l #define rAL ssp->gr[SSP_A].byte.l
#define rA32 ssp->gr[SSP_A].v #define rA32 ssp->gr[SSP_A].v
#define rIJ ssp->r #define rIJ ssp->ptr.r
#define IJind (((op>>6)&4)|(op&3)) #define IJind (((op>>6)&4)|(op&3))
@ -222,45 +222,45 @@
#define GET_PPC_OFFS() ((unsigned int)PC - (unsigned int)svp->iram_rom - 2) #define GET_PPC_OFFS() ((unsigned int)PC - (unsigned int)svp->iram_rom - 2)
#define SET_PC(d) PC = (unsigned short *)svp->iram_rom + d #define SET_PC(d) PC = (unsigned short *)svp->iram_rom + d
#define REG_READ(r) (((r) <= 4) ? ssp->gr[r].h : read_handlers[r]()) #define REG_READ(r) (((r) <= 4) ? ssp->gr[r].byte.h : read_handlers[r]())
#define REG_WRITE(r,d) { \ #define REG_WRITE(r,d) { \
int r1 = r; \ int r1 = r; \
if (r1 >= 4) write_handlers[r1](d); \ if (r1 >= 4) write_handlers[r1](d); \
else if (r1 > 0) ssp->gr[r1].h = d; \ else if (r1 > 0) ssp->gr[r1].byte.h = d; \
} }
// flags /* flags */
#define SSP_FLAG_L (1<<0xc) #define SSP_FLAG_L (1<<0xc)
#define SSP_FLAG_Z (1<<0xd) #define SSP_FLAG_Z (1<<0xd)
#define SSP_FLAG_V (1<<0xe) #define SSP_FLAG_V (1<<0xe)
#define SSP_FLAG_N (1<<0xf) #define SSP_FLAG_N (1<<0xf)
// update ZN according to 32bit ACC. /* update ZN according to 32bit ACC. */
#define UPD_ACC_ZN \ #define UPD_ACC_ZN \
rST &= ~(SSP_FLAG_Z|SSP_FLAG_N); \ rST &= ~(SSP_FLAG_Z|SSP_FLAG_N); \
if (!rA32) rST |= SSP_FLAG_Z; \ if (!rA32) rST |= SSP_FLAG_Z; \
else rST |= (rA32>>16)&SSP_FLAG_N; else rST |= (rA32>>16)&SSP_FLAG_N;
// it seems SVP code never checks for L and OV, so we leave them out. /* it seems SVP code never checks for L and OV, so we leave them out. */
// rST |= (t>>4)&SSP_FLAG_L; /* rST |= (t>>4)&SSP_FLAG_L; */
#define UPD_LZVN \ #define UPD_LZVN \
rST &= ~(SSP_FLAG_L|SSP_FLAG_Z|SSP_FLAG_V|SSP_FLAG_N); \ rST &= ~(SSP_FLAG_L|SSP_FLAG_Z|SSP_FLAG_V|SSP_FLAG_N); \
if (!rA32) rST |= SSP_FLAG_Z; \ if (!rA32) rST |= SSP_FLAG_Z; \
else rST |= (rA32>>16)&SSP_FLAG_N; else rST |= (rA32>>16)&SSP_FLAG_N;
// standard cond processing. /* standard cond processing. */
// again, only Z and N is checked, as SVP doesn't seem to use any other conds. /* again, only Z and N is checked, as SVP doesn't seem to use any other conds. */
#define COND_CHECK \ #define COND_CHECK \
switch (op&0xf0) { \ switch (op&0xf0) { \
case 0x00: cond = 1; break; /* always true */ \ case 0x00: cond = 1; break; /* always true */ \
case 0x50: cond = !((rST ^ (op<<5)) & SSP_FLAG_Z); break; /* Z matches f(?) bit */ \ case 0x50: cond = !((rST ^ (op<<5)) & SSP_FLAG_Z); break; /* Z matches f(?) bit */ \
case 0x70: cond = !((rST ^ (op<<7)) & SSP_FLAG_N); break; /* N matches f(?) bit */ \ case 0x70: cond = !((rST ^ (op<<7)) & SSP_FLAG_N); break; /* N matches f(?) bit */ \
default:elprintf(EL_SVP|EL_ANOMALY, "ssp FIXME: unimplemented cond @ %04x", GET_PPC_OFFS()); break; \ default: break; \
} }
// ops with accumulator. /* ops with accumulator. */
// how is low word really affected by these? /* how is low word really affected by these? */
// nearly sure 'ld A' doesn't affect flags /* nearly sure 'ld A' doesn't affect flags */
#define OP_LDA(x) \ #define OP_LDA(x) \
rA = x rA = x
@ -348,10 +348,10 @@ static int running = 0;
static int last_iram = 0; static int last_iram = 0;
#endif #endif
// ----------------------------------------------------- /* ----------------------------------------------------- */
// register i/o handlers /* register i/o handlers */
// 0-4, 13 /* 0-4, 13 */
static u32 read_unknown(void) static u32 read_unknown(void)
{ {
#ifdef LOG_SVP #ifdef LOG_SVP
@ -367,17 +367,17 @@ static void write_unknown(u32 d)
#endif #endif
} }
// 4 /* 4 */
static void write_ST(u32 d) static void write_ST(u32 d)
{ {
//if ((rST ^ d) & 0x0007) elprintf(EL_SVP, "ssp RPL %i -> %i @ %04x", rST&7, d&7, GET_PPC_OFFS()); /* if ((rST ^ d) & 0x0007) elprintf(EL_SVP, "ssp RPL %i -> %i @ %04x", rST&7, d&7, GET_PPC_OFFS()); */
#ifdef LOG_SVP #ifdef LOG_SVP
if ((rST ^ d) & 0x0f98) elprintf(EL_SVP|EL_ANOMALY, "ssp FIXME ST %04x -> %04x @ %04x", rST, d, GET_PPC_OFFS()); if ((rST ^ d) & 0x0f98) elprintf(EL_SVP|EL_ANOMALY, "ssp FIXME ST %04x -> %04x @ %04x", rST, d, GET_PPC_OFFS());
#endif #endif
rST = d; rST = d;
} }
// 5 /* 5 */
static u32 read_STACK(void) static u32 read_STACK(void)
{ {
--rSTACK; --rSTACK;
@ -401,10 +401,10 @@ static void write_STACK(u32 d)
ssp->stack[rSTACK++] = d; ssp->stack[rSTACK++] = d;
} }
// 6 /* 6 */
static u32 read_PC(void) static u32 read_PC(void)
{ {
//g_cycles--; /* g_cycles--; */
return GET_PC(); return GET_PC();
} }
@ -414,25 +414,25 @@ static void write_PC(u32 d)
g_cycles--; g_cycles--;
} }
// 7 /* 7 */
static u32 read_P(void) static u32 read_P(void)
{ {
int m1 = (signed short)rX; int m1 = (signed short)rX;
int m2 = (signed short)rY; int m2 = (signed short)rY;
rP.v = (m1 * m2 * 2); rP.v = (m1 * m2 * 2);
return rP.h; return rP.byte.h;
} }
// ----------------------------------------------------- /* ----------------------------------------------------- */
static int get_inc(int mode) static int get_inc(int mode)
{ {
int inc = (mode >> 11) & 7; int inc = (mode >> 11) & 7;
if (inc != 0) { if (inc != 0) {
if (inc != 7) inc--; if (inc != 7) inc--;
//inc = (1<<16) << inc; // 0 1 2 4 8 16 32 128 /* inc = (1<<16) << inc; */
inc = 1 << inc; // 0 1 2 4 8 16 32 128 inc = 1 << inc; /* 0 1 2 4 8 16 32 128 */
if (mode & 0x8000) inc = -inc; // decrement mode if (mode & 0x8000) inc = -inc; /* decrement mode */
} }
return inc; return inc;
} }
@ -449,7 +449,7 @@ static u32 pm_io(int reg, int write, u32 d)
{ {
if (ssp->emu_status & SSP_PMC_SET) if (ssp->emu_status & SSP_PMC_SET)
{ {
// this MUST be blind r or w /* this MUST be blind r or w */
if ((*(PC-1) & 0xff0f) && (*(PC-1) & 0xfff0)) { if ((*(PC-1) & 0xff0f) && (*(PC-1) & 0xfff0)) {
#ifdef LOG_SVP #ifdef LOG_SVP
elprintf(EL_SVP|EL_ANOMALY, "ssp FIXME: tried to set PM%i (%c) with non-blind i/o %08x @ %04x", elprintf(EL_SVP|EL_ANOMALY, "ssp FIXME: tried to set PM%i (%c) with non-blind i/o %08x @ %04x",
@ -461,22 +461,20 @@ static u32 pm_io(int reg, int write, u32 d)
#ifdef LOG_SVP #ifdef LOG_SVP
elprintf(EL_SVP, "PM%i (%c) set to %08x @ %04x", reg, write ? 'w' : 'r', rPMC.v, GET_PPC_OFFS()); elprintf(EL_SVP, "PM%i (%c) set to %08x @ %04x", reg, write ? 'w' : 'r', rPMC.v, GET_PPC_OFFS());
#endif #endif
ssp->pmac[write][reg] = rPMC.v;
unsigned int *pmac = &ssp->pmac_read[reg];
pmac[6*write] = rPMC.v;
ssp->emu_status &= ~SSP_PMC_SET; ssp->emu_status &= ~SSP_PMC_SET;
#ifdef LOG_SVP #ifdef LOG_SVP
if ((rPMC.v & 0x7f) == 0x1c && (rPMC.v & 0x7fff0000) == 0) { if ((rPMC.v & 0x7f) == 0x1c && (rPMC.v & 0x7fff0000) == 0) {
elprintf(EL_SVP, "ssp IRAM copy from %06x", (ssp->RAM1[0]-1)<<1); elprintf(EL_SVP, "ssp IRAM copy from %06x", (ssp->mem.bank.RAM1[0]-1)<<1);
#ifdef USE_DEBUGGER #ifdef USE_DEBUGGER
last_iram = (ssp->RAM1[0]-1)<<1; last_iram = (ssp->mem.bank.RAM1[0]-1)<<1;
#endif #endif
} }
#endif #endif
return 0; return 0;
} }
// just in case /* just in case */
if (ssp->emu_status & SSP_PMC_HAVE_ADDR) { if (ssp->emu_status & SSP_PMC_HAVE_ADDR) {
#ifdef LOG_SVP #ifdef LOG_SVP
elprintf(EL_SVP|EL_ANOMALY, "ssp FIXME: PM%i (%c) with only addr set @ %04x", elprintf(EL_SVP|EL_ANOMALY, "ssp FIXME: PM%i (%c) with only addr set @ %04x",
@ -495,13 +493,13 @@ static u32 pm_io(int reg, int write, u32 d)
{ {
/*int mode = ssp->pmac_write[reg]&0xffff; /*int mode = ssp->pmac_write[reg]&0xffff;
int addr = ssp->pmac_write[reg]>>16;*/ int addr = ssp->pmac_write[reg]>>16;*/
int addr = ssp->pmac_write[reg]&0xffff; int addr = ssp->pmac[1][reg]&0xffff;
int mode = ssp->pmac_write[reg]>>16; int mode = ssp->pmac[1][reg]>>16;
#ifdef LOG_SVP #ifdef LOG_SVP
if ((mode & 0xb800) == 0xb800) if ((mode & 0xb800) == 0xb800)
elprintf(EL_SVP|EL_ANOMALY, "ssp FIXME: mode %04x", mode); elprintf(EL_SVP|EL_ANOMALY, "ssp FIXME: mode %04x", mode);
#endif #endif
if ((mode & 0x43ff) == 0x0018) // DRAM if ((mode & 0x43ff) == 0x0018) /* DRAM */
{ {
int inc = get_inc(mode); int inc = get_inc(mode);
#ifdef LOG_SVP #ifdef LOG_SVP
@ -511,9 +509,9 @@ static u32 pm_io(int reg, int write, u32 d)
if (mode & 0x0400) { if (mode & 0x0400) {
overwite_write(dram[addr], d); overwite_write(dram[addr], d);
} else dram[addr] = d; } else dram[addr] = d;
ssp->pmac_write[reg] += inc; ssp->pmac[1][reg] += inc;
} }
else if ((mode & 0xfbff) == 0x4018) // DRAM, cell inc else if ((mode & 0xfbff) == 0x4018) /* DRAM, cell inc */
{ {
#ifdef LOG_SVP #ifdef LOG_SVP
elprintf(EL_SVP, "ssp PM%i DRAM w [%06x] %04x (cell inc, ovrw %i) @ %04x", elprintf(EL_SVP, "ssp PM%i DRAM w [%06x] %04x (cell inc, ovrw %i) @ %04x",
@ -522,10 +520,10 @@ static u32 pm_io(int reg, int write, u32 d)
if (mode & 0x0400) { if (mode & 0x0400) {
overwite_write(dram[addr], d); overwite_write(dram[addr], d);
} else dram[addr] = d; } else dram[addr] = d;
//ssp->pmac_write[reg] += (addr&1) ? (31<<16) : (1<<16); /* ssp->pmac_write[reg] += (addr&1) ? (31<<16) : (1<<16); */
ssp->pmac_write[reg] += (addr&1) ? 31 : 1; ssp->pmac[1][reg] += (addr&1) ? 31 : 1;
} }
else if ((mode & 0x47ff) == 0x001c) // IRAM else if ((mode & 0x47ff) == 0x001c) /* IRAM */
{ {
int inc = get_inc(mode); int inc = get_inc(mode);
#ifdef LOG_SVP #ifdef LOG_SVP
@ -534,7 +532,7 @@ static u32 pm_io(int reg, int write, u32 d)
elprintf(EL_SVP, "ssp IRAM w [%06x] %04x (inc %i)", (addr<<1)&0x7ff, d, inc >> 16); elprintf(EL_SVP, "ssp IRAM w [%06x] %04x (inc %i)", (addr<<1)&0x7ff, d, inc >> 16);
#endif #endif
((unsigned short *)svp->iram_rom)[addr&0x3ff] = d; ((unsigned short *)svp->iram_rom)[addr&0x3ff] = d;
ssp->pmac_write[reg] += inc; ssp->pmac[1][reg] += inc;
} }
#ifdef LOG_SVP #ifdef LOG_SVP
else else
@ -548,10 +546,10 @@ static u32 pm_io(int reg, int write, u32 d)
{ {
/*int mode = ssp->pmac_read[reg]&0xffff; /*int mode = ssp->pmac_read[reg]&0xffff;
int addr = ssp->pmac_read[reg]>>16;*/ int addr = ssp->pmac_read[reg]>>16;*/
int addr = ssp->pmac_read[reg]&0xffff; int addr = ssp->pmac[0][reg]&0xffff;
int mode = ssp->pmac_read[reg]>>16; int mode = ssp->pmac[0][reg]>>16;
if ((mode & 0xfff0) == 0x0800) // ROM, inc 1, verified to be correct if ((mode & 0xfff0) == 0x0800) /* ROM, inc 1, verified to be correct */
{ {
#ifdef LOG_SVP #ifdef LOG_SVP
elprintf(EL_SVP, "ssp ROM r [%06x] %04x", CADDR, elprintf(EL_SVP, "ssp ROM r [%06x] %04x", CADDR,
@ -559,19 +557,19 @@ static u32 pm_io(int reg, int write, u32 d)
#endif #endif
/*if ((signed int)ssp->pmac_read[reg] >> 16 == -1) ssp->pmac_read[reg]++; /*if ((signed int)ssp->pmac_read[reg] >> 16 == -1) ssp->pmac_read[reg]++;
ssp->pmac_read[reg] += 1<<16;*/ ssp->pmac_read[reg] += 1<<16;*/
if ((signed int)(ssp->pmac_read[reg] & 0xffff) == -1) ssp->pmac_read[reg] += 1<<16; if ((signed int)(ssp->pmac[0][reg] & 0xffff) == -1) ssp->pmac[0][reg] += 1<<16;
ssp->pmac_read[reg] ++; ssp->pmac[0][reg] ++;
d = ((unsigned short *)cart.rom)[addr|((mode&0xf)<<16)]; d = ((unsigned short *)cart.rom)[addr|((mode&0xf)<<16)];
} }
else if ((mode & 0x47ff) == 0x0018) // DRAM else if ((mode & 0x47ff) == 0x0018) /* DRAM */
{ {
int inc = get_inc(mode); int inc = get_inc(mode);
#ifdef LOG_SVP #ifdef LOG_SVP
elprintf(EL_SVP, "ssp PM%i DRAM r [%06x] %04x (inc %i)", reg, CADDR, dram[addr], inc >> 16); elprintf(EL_SVP, "ssp PM%i DRAM r [%06x] %04x (inc %i)", reg, CADDR, dram[addr], inc >> 16);
#endif #endif
d = dram[addr]; d = dram[addr];
ssp->pmac_read[reg] += inc; ssp->pmac[0][reg] += inc;
} }
else else
{ {
@ -583,9 +581,8 @@ static u32 pm_io(int reg, int write, u32 d)
} }
} }
// PMC value corresponds to last PMR accessed (not sure). /* PMC value corresponds to last PMR accessed (not sure). */
unsigned int *pmac = &ssp->pmac_read[reg]; rPMC.v = ssp->pmac[write][reg];
rPMC.v = pmac[6*write];
return d; return d;
} }
@ -593,7 +590,7 @@ static u32 pm_io(int reg, int write, u32 d)
return (u32)-1; return (u32)-1;
} }
// 8 /* 8 */
static u32 read_PM0(void) static u32 read_PM0(void)
{ {
u32 d = pm_io(0, 0, 0); u32 d = pm_io(0, 0, 0);
@ -608,7 +605,7 @@ static u32 read_PM0(void)
elprintf(EL_SVP, "det TIGHT loop: PM0"); elprintf(EL_SVP, "det TIGHT loop: PM0");
#endif #endif
} }
rPM0 &= ~2; // ? rPM0 &= ~2; /* ? */
return d; return d;
} }
@ -622,12 +619,12 @@ static void write_PM0(u32 d)
rPM0 = d; rPM0 = d;
} }
// 9 /* 9 */
static u32 read_PM1(void) static u32 read_PM1(void)
{ {
u32 d = pm_io(1, 0, 0); u32 d = pm_io(1, 0, 0);
if (d != (u32)-1) return d; if (d != (u32)-1) return d;
// can be removed? /* can be removed? */
#ifdef LOG_SVP #ifdef LOG_SVP
elprintf(EL_SVP|EL_ANOMALY, "PM1 raw r %04x @ %04x", rPM1, GET_PPC_OFFS()); elprintf(EL_SVP|EL_ANOMALY, "PM1 raw r %04x @ %04x", rPM1, GET_PPC_OFFS());
#endif #endif
@ -638,19 +635,19 @@ static void write_PM1(u32 d)
{ {
u32 r = pm_io(1, 1, d); u32 r = pm_io(1, 1, d);
if (r != (u32)-1) return; if (r != (u32)-1) return;
// can be removed? /* can be removed? */
#ifdef LOG_SVP #ifdef LOG_SVP
elprintf(EL_SVP|EL_ANOMALY, "PM1 raw w %04x @ %04x", d, GET_PPC_OFFS()); elprintf(EL_SVP|EL_ANOMALY, "PM1 raw w %04x @ %04x", d, GET_PPC_OFFS());
#endif #endif
rPM1 = d; rPM1 = d;
} }
// 10 /* 10 */
static u32 read_PM2(void) static u32 read_PM2(void)
{ {
u32 d = pm_io(2, 0, 0); u32 d = pm_io(2, 0, 0);
if (d != (u32)-1) return d; if (d != (u32)-1) return d;
// can be removed? /* can be removed? */
#ifdef LOG_SVP #ifdef LOG_SVP
elprintf(EL_SVP|EL_ANOMALY, "PM2 raw r %04x @ %04x", rPM2, GET_PPC_OFFS()); elprintf(EL_SVP|EL_ANOMALY, "PM2 raw r %04x @ %04x", rPM2, GET_PPC_OFFS());
#endif #endif
@ -661,17 +658,17 @@ static void write_PM2(u32 d)
{ {
u32 r = pm_io(2, 1, d); u32 r = pm_io(2, 1, d);
if (r != (u32)-1) return; if (r != (u32)-1) return;
// can be removed? /* can be removed? */
#ifdef LOG_SVP #ifdef LOG_SVP
elprintf(EL_SVP|EL_ANOMALY, "PM2 raw w %04x @ %04x", d, GET_PPC_OFFS()); elprintf(EL_SVP|EL_ANOMALY, "PM2 raw w %04x @ %04x", d, GET_PPC_OFFS());
#endif #endif
rPM2 = d; rPM2 = d;
} }
// 11 /* 11 */
static u32 read_XST(void) static u32 read_XST(void)
{ {
// can be removed? /* can be removed? */
u32 d = pm_io(3, 0, 0); u32 d = pm_io(3, 0, 0);
if (d != (u32)-1) return d; if (d != (u32)-1) return d;
#ifdef LOG_SVP #ifdef LOG_SVP
@ -682,7 +679,7 @@ static u32 read_XST(void)
static void write_XST(u32 d) static void write_XST(u32 d)
{ {
// can be removed? /* can be removed? */
u32 r = pm_io(3, 1, d); u32 r = pm_io(3, 1, d);
if (r != (u32)-1) return; if (r != (u32)-1) return;
#ifdef LOG_SVP #ifdef LOG_SVP
@ -692,7 +689,7 @@ static void write_XST(u32 d)
rXST = d; rXST = d;
} }
// 12 /* 12 */
static u32 read_PM4(void) static u32 read_PM4(void)
{ {
u32 d = pm_io(4, 0, 0); u32 d = pm_io(4, 0, 0);
@ -713,7 +710,7 @@ static u32 read_PM4(void)
} }
} }
if (d != (u32)-1) return d; if (d != (u32)-1) return d;
// can be removed? /* can be removed? */
#ifdef LOG_SVP #ifdef LOG_SVP
elprintf(EL_SVP|EL_ANOMALY, "PM4 raw r %04x @ %04x", rPM4, GET_PPC_OFFS()); elprintf(EL_SVP|EL_ANOMALY, "PM4 raw r %04x @ %04x", rPM4, GET_PPC_OFFS());
#endif #endif
@ -724,64 +721,64 @@ static void write_PM4(u32 d)
{ {
u32 r = pm_io(4, 1, d); u32 r = pm_io(4, 1, d);
if (r != (u32)-1) return; if (r != (u32)-1) return;
// can be removed? /* can be removed? */
#ifdef LOG_SVP #ifdef LOG_SVP
elprintf(EL_SVP|EL_ANOMALY, "PM4 raw w %04x @ %04x", d, GET_PPC_OFFS()); elprintf(EL_SVP|EL_ANOMALY, "PM4 raw w %04x @ %04x", d, GET_PPC_OFFS());
#endif #endif
rPM4 = d; rPM4 = d;
} }
// 14 /* 14 */
static u32 read_PMC(void) static u32 read_PMC(void)
{ {
#ifdef LOG_SVP #ifdef LOG_SVP
elprintf(EL_SVP, "PMC r a %04x (st %c) @ %04x", rPMC.h, elprintf(EL_SVP, "PMC r a %04x (st %c) @ %04x", rPMC.byte.h,
(ssp->emu_status & SSP_PMC_HAVE_ADDR) ? 'm' : 'a', GET_PPC_OFFS()); (ssp->emu_status & SSP_PMC_HAVE_ADDR) ? 'm' : 'a', GET_PPC_OFFS());
#endif #endif
if (ssp->emu_status & SSP_PMC_HAVE_ADDR) { if (ssp->emu_status & SSP_PMC_HAVE_ADDR) {
//if (ssp->emu_status & SSP_PMC_SET) /* if (ssp->emu_status & SSP_PMC_SET) */
// elprintf(EL_ANOMALY|EL_SVP, "prev PMC not used @ %04x", GET_PPC_OFFS()); /* elprintf(EL_ANOMALY|EL_SVP, "prev PMC not used @ %04x", GET_PPC_OFFS()); */
ssp->emu_status |= SSP_PMC_SET; ssp->emu_status |= SSP_PMC_SET;
ssp->emu_status &= ~SSP_PMC_HAVE_ADDR; ssp->emu_status &= ~SSP_PMC_HAVE_ADDR;
//return ((rPMC.h << 4) & 0xfff0) | ((rPMC.h >> 4) & 0xf); /* return ((rPMC.h << 4) & 0xfff0) | ((rPMC.h >> 4) & 0xf); */
return ((rPMC.l << 4) & 0xfff0) | ((rPMC.l >> 4) & 0xf); return ((rPMC.byte.l << 4) & 0xfff0) | ((rPMC.byte.l >> 4) & 0xf);
} else { } else {
ssp->emu_status |= SSP_PMC_HAVE_ADDR; ssp->emu_status |= SSP_PMC_HAVE_ADDR;
//return rPMC.h; /* return rPMC.h; */
return rPMC.l; return rPMC.byte.l;
} }
} }
static void write_PMC(u32 d) static void write_PMC(u32 d)
{ {
if (ssp->emu_status & SSP_PMC_HAVE_ADDR) { if (ssp->emu_status & SSP_PMC_HAVE_ADDR) {
//if (ssp->emu_status & SSP_PMC_SET) /* if (ssp->emu_status & SSP_PMC_SET) */
// elprintf(EL_ANOMALY|EL_SVP, "prev PMC not used @ %04x", GET_PPC_OFFS()); /* elprintf(EL_ANOMALY|EL_SVP, "prev PMC not used @ %04x", GET_PPC_OFFS()); */
ssp->emu_status |= SSP_PMC_SET; ssp->emu_status |= SSP_PMC_SET;
ssp->emu_status &= ~SSP_PMC_HAVE_ADDR; ssp->emu_status &= ~SSP_PMC_HAVE_ADDR;
//rPMC.l = d; /* rPMC.l = d; */
rPMC.h = d; rPMC.byte.h = d;
#ifdef LOG_SVP #ifdef LOG_SVP
elprintf(EL_SVP, "PMC w m %04x @ %04x", rPMC.l, GET_PPC_OFFS()); elprintf(EL_SVP, "PMC w m %04x @ %04x", rPMC.byte.l, GET_PPC_OFFS());
#endif #endif
} else { } else {
ssp->emu_status |= SSP_PMC_HAVE_ADDR; ssp->emu_status |= SSP_PMC_HAVE_ADDR;
//rPMC.h = d; /* rPMC.h = d; */
rPMC.l = d; rPMC.byte.l = d;
#ifdef LOG_SVP #ifdef LOG_SVP
elprintf(EL_SVP, "PMC w a %04x @ %04x", rPMC.h, GET_PPC_OFFS()); elprintf(EL_SVP, "PMC w a %04x @ %04x", rPMC.byte.h, GET_PPC_OFFS());
#endif #endif
} }
} }
// 15 /* 15 */
static u32 read_AL(void) static u32 read_AL(void)
{ {
if (*(PC-1) == 0x000f) { if (*(PC-1) == 0x000f) {
#ifdef LOG_SVP #ifdef LOG_SVP
elprintf(EL_SVP, "ssp dummy PM assign %08x @ %04x", rPMC.v, GET_PPC_OFFS()); elprintf(EL_SVP, "ssp dummy PM assign %08x @ %04x", rPMC.v, GET_PPC_OFFS());
#endif #endif
ssp->emu_status &= ~(SSP_PMC_SET|SSP_PMC_HAVE_ADDR); // ? ssp->emu_status &= ~(SSP_PMC_SET|SSP_PMC_HAVE_ADDR); /* ? */
} }
return rAL; return rAL;
} }
@ -797,96 +794,95 @@ typedef void (*write_func_t)(u32 d);
static read_func_t read_handlers[16] = static read_func_t read_handlers[16] =
{ {
read_unknown, read_unknown, read_unknown, read_unknown, // -, X, Y, A read_unknown, read_unknown, read_unknown, read_unknown, /* -, X, Y, A */
read_unknown, // 4 ST read_unknown, /* 4 ST */
read_STACK, read_STACK,
read_PC, read_PC,
read_P, read_P,
read_PM0, // 8 read_PM0, /* 8 */
read_PM1, read_PM1,
read_PM2, read_PM2,
read_XST, read_XST,
read_PM4, // 12 read_PM4, /* 12 */
read_unknown, // 13 gr13 read_unknown, /* 13 gr13 */
read_PMC, read_PMC,
read_AL read_AL
}; };
static write_func_t write_handlers[16] = static write_func_t write_handlers[16] =
{ {
write_unknown, write_unknown, write_unknown, write_unknown, // -, X, Y, A write_unknown, write_unknown, write_unknown, write_unknown, /* -, X, Y, A */
// write_unknown, // 4 ST /* write_unknown, */ /* 4 ST */
write_ST, // 4 ST (debug hook) write_ST, /* 4 ST (debug hook) */
write_STACK, write_STACK,
write_PC, write_PC,
write_unknown, // 7 P write_unknown, /* 7 P */
write_PM0, // 8 write_PM0, /* 8 */
write_PM1, write_PM1,
write_PM2, write_PM2,
write_XST, write_XST,
write_PM4, // 12 write_PM4, /* 12 */
write_unknown, // 13 gr13 write_unknown, /* 13 gr13 */
write_PMC, write_PMC,
write_AL write_AL
}; };
// ----------------------------------------------------- /* ----------------------------------------------------- */
// pointer register handlers /* pointer register handlers */
//
#define ptr1_read(op) ptr1_read_(op&3,(op>>6)&4,(op<<1)&0x18) #define ptr1_read(op) ptr1_read_(op&3,(op>>6)&4,(op<<1)&0x18)
static u32 ptr1_read_(int ri, int isj2, int modi3) static u32 ptr1_read_(int ri, int isj2, int modi3)
{ {
//int t = (op&3) | ((op>>6)&4) | ((op<<1)&0x18); /* int t = (op&3) | ((op>>6)&4) | ((op<<1)&0x18); */
u32 mask, add = 0, t = ri | isj2 | modi3; u32 mask, add = 0, t = ri | isj2 | modi3;
unsigned char *rp = NULL; unsigned char *rp = NULL;
switch (t) switch (t)
{ {
// mod=0 (00) /* mod=0 (00) */
case 0x00: case 0x00:
case 0x01: case 0x01:
case 0x02: return ssp->RAM0[ssp->r0[t&3]]; case 0x02: return ssp->mem.bank.RAM0[ssp->ptr.bank.r0[t&3]];
case 0x03: return ssp->RAM0[0]; case 0x03: return ssp->mem.bank.RAM0[0];
case 0x04: case 0x04:
case 0x05: case 0x05:
case 0x06: return ssp->RAM1[ssp->r1[t&3]]; case 0x06: return ssp->mem.bank.RAM1[ssp->ptr.bank.r1[t&3]];
case 0x07: return ssp->RAM1[0]; case 0x07: return ssp->mem.bank.RAM1[0];
// mod=1 (01), "+!" /* mod=1 (01), "+!" */
case 0x08: case 0x08:
case 0x09: case 0x09:
case 0x0a: return ssp->RAM0[ssp->r0[t&3]++]; case 0x0a: return ssp->mem.bank.RAM0[ssp->ptr.bank.r0[t&3]++];
case 0x0b: return ssp->RAM0[1]; case 0x0b: return ssp->mem.bank.RAM0[1];
case 0x0c: case 0x0c:
case 0x0d: case 0x0d:
case 0x0e: return ssp->RAM1[ssp->r1[t&3]++]; case 0x0e: return ssp->mem.bank.RAM1[ssp->ptr.bank.r1[t&3]++];
case 0x0f: return ssp->RAM1[1]; case 0x0f: return ssp->mem.bank.RAM1[1];
// mod=2 (10), "-" /* mod=2 (10), "-" */
case 0x10: case 0x10:
case 0x11: case 0x11:
case 0x12: rp = &ssp->r0[t&3]; t = ssp->RAM0[*rp]; case 0x12: rp = &ssp->ptr.bank.r0[t&3]; t = ssp->mem.bank.RAM0[*rp];
if (!(rST&7)) { (*rp)--; return t; } if (!(rST&7)) { (*rp)--; return t; }
add = -1; goto modulo; add = -1; goto modulo;
case 0x13: return ssp->RAM0[2]; case 0x13: return ssp->mem.bank.RAM0[2];
case 0x14: case 0x14:
case 0x15: case 0x15:
case 0x16: rp = &ssp->r1[t&3]; t = ssp->RAM1[*rp]; case 0x16: rp = &ssp->ptr.bank.r1[t&3]; t = ssp->mem.bank.RAM1[*rp];
if (!(rST&7)) { (*rp)--; return t; } if (!(rST&7)) { (*rp)--; return t; }
add = -1; goto modulo; add = -1; goto modulo;
case 0x17: return ssp->RAM1[2]; case 0x17: return ssp->mem.bank.RAM1[2];
// mod=3 (11), "+" /* mod=3 (11), "+" */
case 0x18: case 0x18:
case 0x19: case 0x19:
case 0x1a: rp = &ssp->r0[t&3]; t = ssp->RAM0[*rp]; case 0x1a: rp = &ssp->ptr.bank.r0[t&3]; t = ssp->mem.bank.RAM0[*rp];
if (!(rST&7)) { (*rp)++; return t; } if (!(rST&7)) { (*rp)++; return t; }
add = 1; goto modulo; add = 1; goto modulo;
case 0x1b: return ssp->RAM0[3]; case 0x1b: return ssp->mem.bank.RAM0[3];
case 0x1c: case 0x1c:
case 0x1d: case 0x1d:
case 0x1e: rp = &ssp->r1[t&3]; t = ssp->RAM1[*rp]; case 0x1e: rp = &ssp->ptr.bank.r1[t&3]; t = ssp->mem.bank.RAM1[*rp];
if (!(rST&7)) { (*rp)++; return t; } if (!(rST&7)) { (*rp)++; return t; }
add = 1; goto modulo; add = 1; goto modulo;
case 0x1f: return ssp->RAM1[3]; case 0x1f: return ssp->mem.bank.RAM1[3];
} }
return 0; return 0;
@ -902,43 +898,43 @@ static void ptr1_write(int op, u32 d)
int t = (op&3) | ((op>>6)&4) | ((op<<1)&0x18); int t = (op&3) | ((op>>6)&4) | ((op<<1)&0x18);
switch (t) switch (t)
{ {
// mod=0 (00) /* mod=0 (00) */
case 0x00: case 0x00:
case 0x01: case 0x01:
case 0x02: ssp->RAM0[ssp->r0[t&3]] = d; return; case 0x02: ssp->mem.bank.RAM0[ssp->ptr.bank.r0[t&3]] = d; return;
case 0x03: ssp->RAM0[0] = d; return; case 0x03: ssp->mem.bank.RAM0[0] = d; return;
case 0x04: case 0x04:
case 0x05: case 0x05:
case 0x06: ssp->RAM1[ssp->r1[t&3]] = d; return; case 0x06: ssp->mem.bank.RAM1[ssp->ptr.bank.r1[t&3]] = d; return;
case 0x07: ssp->RAM1[0] = d; return; case 0x07: ssp->mem.bank.RAM1[0] = d; return;
// mod=1 (01), "+!" /* mod=1 (01), "+!" */
// mod=3, "+" /* mod=3, "+" */
case 0x08: case 0x08:
case 0x18: case 0x18:
case 0x09: case 0x09:
case 0x19: case 0x19:
case 0x0a: case 0x0a:
case 0x1a: ssp->RAM0[ssp->r0[t&3]++] = d; return; case 0x1a: ssp->mem.bank.RAM0[ssp->ptr.bank.r0[t&3]++] = d; return;
case 0x0b: ssp->RAM0[1] = d; return; case 0x0b: ssp->mem.bank.RAM0[1] = d; return;
case 0x0c: case 0x0c:
case 0x1c: case 0x1c:
case 0x0d: case 0x0d:
case 0x1d: case 0x1d:
case 0x0e: case 0x0e:
case 0x1e: ssp->RAM1[ssp->r1[t&3]++] = d; return; case 0x1e: ssp->mem.bank.RAM1[ssp->ptr.bank.r1[t&3]++] = d; return;
case 0x0f: ssp->RAM1[1] = d; return; case 0x0f: ssp->mem.bank.RAM1[1] = d; return;
// mod=2 (10), "-" /* mod=2 (10), "-" */
case 0x10: case 0x10:
case 0x11: case 0x11:
case 0x12: ssp->RAM0[ssp->r0[t&3]--] = d; return; case 0x12: ssp->mem.bank.RAM0[ssp->ptr.bank.r0[t&3]--] = d; return;
case 0x13: ssp->RAM0[2] = d; return; case 0x13: ssp->mem.bank.RAM0[2] = d; return;
case 0x14: case 0x14:
case 0x15: case 0x15:
case 0x16: ssp->RAM1[ssp->r1[t&3]--] = d; return; case 0x16: ssp->mem.bank.RAM1[ssp->ptr.bank.r1[t&3]--] = d; return;
case 0x17: ssp->RAM1[2] = d; return; case 0x17: ssp->mem.bank.RAM1[2] = d; return;
// mod=3 (11) /* mod=3 (11) */
case 0x1b: ssp->RAM0[3] = d; return; case 0x1b: ssp->mem.bank.RAM0[3] = d; return;
case 0x1f: ssp->RAM1[3] = d; return; case 0x1f: ssp->mem.bank.RAM1[3] = d; return;
} }
} }
@ -947,33 +943,36 @@ static u32 ptr2_read(int op)
int mv = 0, t = (op&3) | ((op>>6)&4) | ((op<<1)&0x18); int mv = 0, t = (op&3) | ((op>>6)&4) | ((op<<1)&0x18);
switch (t) switch (t)
{ {
// mod=0 (00) /* mod=0 (00) */
case 0x00: case 0x00:
case 0x01: case 0x01:
case 0x02: mv = ssp->RAM0[ssp->r0[t&3]]++; break; case 0x02: mv = ssp->mem.bank.RAM0[ssp->ptr.bank.r0[t&3]]++; break;
case 0x03: mv = ssp->RAM0[0]++; break; case 0x03: mv = ssp->mem.bank.RAM0[0]++; break;
case 0x04: case 0x04:
case 0x05: case 0x05:
case 0x06: mv = ssp->RAM1[ssp->r1[t&3]]++; break; case 0x06: mv = ssp->mem.bank.RAM1[ssp->ptr.bank.r1[t&3]]++; break;
case 0x07: mv = ssp->RAM1[0]++; break; case 0x07: mv = ssp->mem.bank.RAM1[0]++; break;
// mod=1 (01) /* mod=1 (01) */
case 0x0b: mv = ssp->RAM0[1]++; break; case 0x0b: mv = ssp->mem.bank.RAM0[1]++; break;
case 0x0f: mv = ssp->RAM1[1]++; break; case 0x0f: mv = ssp->mem.bank.RAM1[1]++; break;
// mod=2 (10) /* mod=2 (10) */
case 0x13: mv = ssp->RAM0[2]++; break; case 0x13: mv = ssp->mem.bank.RAM0[2]++; break;
case 0x17: mv = ssp->RAM1[2]++; break; case 0x17: mv = ssp->mem.bank.RAM1[2]++; break;
// mod=3 (11) /* mod=3 (11) */
case 0x1b: mv = ssp->RAM0[3]++; break; case 0x1b: mv = ssp->mem.bank.RAM0[3]++; break;
case 0x1f: mv = ssp->RAM1[3]++; break; case 0x1f: mv = ssp->mem.bank.RAM1[3]++; break;
default: elprintf(EL_SVP|EL_ANOMALY, "ssp FIXME: invalid mod in ((rX))? @ %04x", GET_PPC_OFFS()); default:
return 0; #ifdef LOG_SVP
elprintf(EL_SVP|EL_ANOMALY, "ssp FIXME: invalid mod in ((rX))? @ %04x", GET_PPC_OFFS());
#endif
return 0;
} }
return ((unsigned short *)svp->iram_rom)[mv]; return ((unsigned short *)svp->iram_rom)[mv];
} }
// ----------------------------------------------------- /* ----------------------------------------------------- */
void ssp1601_reset(ssp1601_t *l_ssp) void ssp1601_reset(ssp1601_t *l_ssp)
{ {
@ -981,7 +980,7 @@ void ssp1601_reset(ssp1601_t *l_ssp)
ssp->emu_status = 0; ssp->emu_status = 0;
ssp->gr[SSP_GR0].v = 0xffff0000; ssp->gr[SSP_GR0].v = 0xffff0000;
rPC = 0x400; rPC = 0x400;
rSTACK = 0; // ? using ascending stack rSTACK = 0; /* ? using ascending stack */
rST = 0; rST = 0;
} }
@ -989,7 +988,7 @@ void ssp1601_reset(ssp1601_t *l_ssp)
#ifdef USE_DEBUGGER #ifdef USE_DEBUGGER
static void debug_dump(void) static void debug_dump(void)
{ {
printf("GR0: %04x X: %04x Y: %04x A: %08x\n", ssp->gr[SSP_GR0].h, rX, rY, ssp->gr[SSP_A].v); printf("GR0: %04x X: %04x Y: %04x A: %08x\n", ssp->gr[SSP_GR0].byte.h, rX, rY, ssp->gr[SSP_A].v);
printf("PC: %04x (%04x) P: %08x\n", GET_PC(), GET_PC() << 1, ssp->gr[SSP_P].v); printf("PC: %04x (%04x) P: %08x\n", GET_PC(), GET_PC() << 1, ssp->gr[SSP_P].v);
printf("PM0: %04x PM1: %04x PM2: %04x\n", rPM0, rPM1, rPM2); printf("PM0: %04x PM1: %04x PM2: %04x\n", rPM0, rPM1, rPM2);
printf("XST: %04x PM4: %04x PMC: %08x\n", rXST, rPM4, ssp->gr[SSP_PMC].v); printf("XST: %04x PM4: %04x PMC: %08x\n", rXST, rPM4, ssp->gr[SSP_PMC].v);
@ -1010,7 +1009,7 @@ static void debug_dump_mem(void)
if (h == 16) printf("RAM1\n"); if (h == 16) printf("RAM1\n");
printf("%03x:", h*16); printf("%03x:", h*16);
for (i = 0; i < 16; i++) for (i = 0; i < 16; i++)
printf(" %04x", ssp->RAM[h*16+i]); printf(" %04x", ssp->mem.RAM[h*16+i]);
printf("\n"); printf("\n");
} }
} }
@ -1084,7 +1083,7 @@ static void debug(unsigned int pc, unsigned int op)
} }
} }
} }
#endif // USE_DEBUGGER #endif /* USE_DEBUGGER */
void ssp1601_run(int cycles) void ssp1601_run(int cycles)
@ -1103,12 +1102,12 @@ void ssp1601_run(int cycles)
#endif #endif
switch (op >> 9) switch (op >> 9)
{ {
// ld d, s /* ld d, s */
case 0x00: case 0x00:
if (op == 0) break; // nop if (op == 0) break; /* nop */
if (op == ((SSP_A<<4)|SSP_P)) { // A <- P if (op == ((SSP_A<<4)|SSP_P)) { /* A <- P */
// not sure. MAME claims that only hi word is transfered. /* not sure. MAME claims that only hi word is transfered. */
read_P(); // update P read_P(); /* update P */
rA32 = rP.v; rA32 = rP.v;
} }
else else
@ -1118,37 +1117,37 @@ void ssp1601_run(int cycles)
} }
break; break;
// ld d, (ri) /* ld d, (ri) */
case 0x01: tmpv = ptr1_read(op); REG_WRITE((op & 0xf0) >> 4, tmpv); break; case 0x01: tmpv = ptr1_read(op); REG_WRITE((op & 0xf0) >> 4, tmpv); break;
// ld (ri), s /* ld (ri), s */
case 0x02: tmpv = REG_READ((op & 0xf0) >> 4); ptr1_write(op, tmpv); break; case 0x02: tmpv = REG_READ((op & 0xf0) >> 4); ptr1_write(op, tmpv); break;
// ldi d, imm /* ldi d, imm */
case 0x04: tmpv = *PC++; REG_WRITE((op & 0xf0) >> 4, tmpv); break; case 0x04: tmpv = *PC++; REG_WRITE((op & 0xf0) >> 4, tmpv); break;
// ld d, ((ri)) /* ld d, ((ri)) */
case 0x05: tmpv = ptr2_read(op); REG_WRITE((op & 0xf0) >> 4, tmpv); break; case 0x05: tmpv = ptr2_read(op); REG_WRITE((op & 0xf0) >> 4, tmpv); break;
// ldi (ri), imm /* ldi (ri), imm */
case 0x06: tmpv = *PC++; ptr1_write(op, tmpv); break; case 0x06: tmpv = *PC++; ptr1_write(op, tmpv); break;
// ld adr, a /* ld adr, a */
case 0x07: ssp->RAM[op & 0x1ff] = rA; break; case 0x07: ssp->mem.RAM[op & 0x1ff] = rA; break;
// ld d, ri /* ld d, ri */
case 0x09: tmpv = rIJ[(op&3)|((op>>6)&4)]; REG_WRITE((op & 0xf0) >> 4, tmpv); break; case 0x09: tmpv = rIJ[(op&3)|((op>>6)&4)]; REG_WRITE((op & 0xf0) >> 4, tmpv); break;
// ld ri, s /* ld ri, s */
case 0x0a: rIJ[(op&3)|((op>>6)&4)] = REG_READ((op & 0xf0) >> 4); break; case 0x0a: rIJ[(op&3)|((op>>6)&4)] = REG_READ((op & 0xf0) >> 4); break;
// ldi ri, simm /* ldi ri, simm */
case 0x0c: case 0x0c:
case 0x0d: case 0x0d:
case 0x0e: case 0x0e:
case 0x0f: rIJ[(op>>8)&7] = op; break; case 0x0f: rIJ[(op>>8)&7] = op; break;
// call cond, addr /* call cond, addr */
case 0x24: { case 0x24: {
int cond = 0; int cond = 0;
COND_CHECK COND_CHECK
@ -1157,10 +1156,10 @@ void ssp1601_run(int cycles)
break; break;
} }
// ld d, (a) /* ld d, (a) */
case 0x25: tmpv = ((unsigned short *)svp->iram_rom)[rA]; REG_WRITE((op & 0xf0) >> 4, tmpv); break; case 0x25: tmpv = ((unsigned short *)svp->iram_rom)[rA]; REG_WRITE((op & 0xf0) >> 4, tmpv); break;
// bra cond, addr /* bra cond, addr */
case 0x26: { case 0x26: {
int cond = 0; int cond = 0;
COND_CHECK COND_CHECK
@ -1169,16 +1168,16 @@ void ssp1601_run(int cycles)
break; break;
} }
// mod cond, op /* mod cond, op */
case 0x48: { case 0x48: {
int cond = 0; int cond = 0;
COND_CHECK COND_CHECK
if (cond) { if (cond) {
switch (op & 7) { switch (op & 7) {
case 2: rA32 = (signed int)rA32 >> 1; break; // shr (arithmetic) case 2: rA32 = (signed int)rA32 >> 1; break; /* shr (arithmetic) */
case 3: rA32 <<= 1; break; // shl case 3: rA32 <<= 1; break; /* shl */
case 6: rA32 = -(signed int)rA32; break; // neg case 6: rA32 = -(signed int)rA32; break; /* neg */
case 7: if ((int)rA32 < 0) rA32 = -(signed int)rA32; break; // abs case 7: if ((int)rA32 < 0) rA32 = -(signed int)rA32; break; /* abs */
default: default:
#ifdef LOG_SVP #ifdef LOG_SVP
elprintf(EL_SVP|EL_ANOMALY, "ssp FIXME: unhandled mod %i @ %04x", elprintf(EL_SVP|EL_ANOMALY, "ssp FIXME: unhandled mod %i @ %04x",
@ -1186,47 +1185,47 @@ void ssp1601_run(int cycles)
#endif #endif
break; break;
} }
UPD_ACC_ZN // ? UPD_ACC_ZN /* ? */
} }
break; break;
} }
// mpys? /* mpys? */
case 0x1b: case 0x1b:
#ifdef LOG_SVP #ifdef LOG_SVP
if (!(op&0x100)) elprintf(EL_SVP|EL_ANOMALY, "ssp FIXME: no b bit @ %04x", GET_PPC_OFFS()); if (!(op&0x100)) elprintf(EL_SVP|EL_ANOMALY, "ssp FIXME: no b bit @ %04x", GET_PPC_OFFS());
#endif #endif
read_P(); // update P read_P(); /* update P */
rA32 -= rP.v; // maybe only upper word? rA32 -= rP.v; /* maybe only upper word? */
UPD_ACC_ZN // there checking flags after this UPD_ACC_ZN /* there checking flags after this */
rX = ptr1_read_(op&3, 0, (op<<1)&0x18); // ri (maybe rj?) rX = ptr1_read_(op&3, 0, (op<<1)&0x18); /* ri (maybe rj?) */
rY = ptr1_read_((op>>4)&3, 4, (op>>3)&0x18); // rj rY = ptr1_read_((op>>4)&3, 4, (op>>3)&0x18); /* rj */
break; break;
// mpya (rj), (ri), b /* mpya (rj), (ri), b */
case 0x4b: case 0x4b:
#ifdef LOG_SVP #ifdef LOG_SVP
if (!(op&0x100)) elprintf(EL_SVP|EL_ANOMALY, "ssp FIXME: no b bit @ %04x", GET_PPC_OFFS()); if (!(op&0x100)) elprintf(EL_SVP|EL_ANOMALY, "ssp FIXME: no b bit @ %04x", GET_PPC_OFFS());
#endif #endif
read_P(); // update P read_P(); /* update P */
rA32 += rP.v; // confirmed to be 32bit rA32 += rP.v; /* confirmed to be 32bit */
UPD_ACC_ZN // ? UPD_ACC_ZN /* ? */
rX = ptr1_read_(op&3, 0, (op<<1)&0x18); // ri (maybe rj?) rX = ptr1_read_(op&3, 0, (op<<1)&0x18); /* ri (maybe rj?) */
rY = ptr1_read_((op>>4)&3, 4, (op>>3)&0x18); // rj rY = ptr1_read_((op>>4)&3, 4, (op>>3)&0x18); /* rj */
break; break;
// mld (rj), (ri), b /* mld (rj), (ri), b */
case 0x5b: case 0x5b:
#ifdef LOG_SVP #ifdef LOG_SVP
if (!(op&0x100)) elprintf(EL_SVP|EL_ANOMALY, "ssp FIXME: no b bit @ %04x", GET_PPC_OFFS()); if (!(op&0x100)) elprintf(EL_SVP|EL_ANOMALY, "ssp FIXME: no b bit @ %04x", GET_PPC_OFFS());
#endif #endif
rA32 = 0; rA32 = 0;
rST &= 0x0fff; // ? rST &= 0x0fff; /* ? */
rX = ptr1_read_(op&3, 0, (op<<1)&0x18); // ri (maybe rj?) rX = ptr1_read_(op&3, 0, (op<<1)&0x18); /* ri (maybe rj?) */
rY = ptr1_read_((op>>4)&3, 4, (op>>3)&0x18); // rj rY = ptr1_read_((op>>4)&3, 4, (op>>3)&0x18); /* rj */
break; break;
// OP a, s /* OP a, s */
case 0x10: OP_CHECK32(OP_SUBA32); tmpv = REG_READ(op & 0x0f); OP_SUBA(tmpv); break; case 0x10: OP_CHECK32(OP_SUBA32); tmpv = REG_READ(op & 0x0f); OP_SUBA(tmpv); break;
case 0x30: OP_CHECK32(OP_CMPA32); tmpv = REG_READ(op & 0x0f); OP_CMPA(tmpv); break; case 0x30: OP_CHECK32(OP_CMPA32); tmpv = REG_READ(op & 0x0f); OP_CMPA(tmpv); break;
case 0x40: OP_CHECK32(OP_ADDA32); tmpv = REG_READ(op & 0x0f); OP_ADDA(tmpv); break; case 0x40: OP_CHECK32(OP_ADDA32); tmpv = REG_READ(op & 0x0f); OP_ADDA(tmpv); break;
@ -1234,7 +1233,7 @@ void ssp1601_run(int cycles)
case 0x60: OP_CHECK32(OP_ORA32 ); tmpv = REG_READ(op & 0x0f); OP_ORA (tmpv); break; case 0x60: OP_CHECK32(OP_ORA32 ); tmpv = REG_READ(op & 0x0f); OP_ORA (tmpv); break;
case 0x70: OP_CHECK32(OP_EORA32); tmpv = REG_READ(op & 0x0f); OP_EORA(tmpv); break; case 0x70: OP_CHECK32(OP_EORA32); tmpv = REG_READ(op & 0x0f); OP_EORA(tmpv); break;
// OP a, (ri) /* OP a, (ri) */
case 0x11: tmpv = ptr1_read(op); OP_SUBA(tmpv); break; case 0x11: tmpv = ptr1_read(op); OP_SUBA(tmpv); break;
case 0x31: tmpv = ptr1_read(op); OP_CMPA(tmpv); break; case 0x31: tmpv = ptr1_read(op); OP_CMPA(tmpv); break;
case 0x41: tmpv = ptr1_read(op); OP_ADDA(tmpv); break; case 0x41: tmpv = ptr1_read(op); OP_ADDA(tmpv); break;
@ -1242,16 +1241,16 @@ void ssp1601_run(int cycles)
case 0x61: tmpv = ptr1_read(op); OP_ORA (tmpv); break; case 0x61: tmpv = ptr1_read(op); OP_ORA (tmpv); break;
case 0x71: tmpv = ptr1_read(op); OP_EORA(tmpv); break; case 0x71: tmpv = ptr1_read(op); OP_EORA(tmpv); break;
// OP a, adr /* OP a, adr */
case 0x03: tmpv = ssp->RAM[op & 0x1ff]; OP_LDA (tmpv); break; case 0x03: tmpv = ssp->mem.RAM[op & 0x1ff]; OP_LDA (tmpv); break;
case 0x13: tmpv = ssp->RAM[op & 0x1ff]; OP_SUBA(tmpv); break; case 0x13: tmpv = ssp->mem.RAM[op & 0x1ff]; OP_SUBA(tmpv); break;
case 0x33: tmpv = ssp->RAM[op & 0x1ff]; OP_CMPA(tmpv); break; case 0x33: tmpv = ssp->mem.RAM[op & 0x1ff]; OP_CMPA(tmpv); break;
case 0x43: tmpv = ssp->RAM[op & 0x1ff]; OP_ADDA(tmpv); break; case 0x43: tmpv = ssp->mem.RAM[op & 0x1ff]; OP_ADDA(tmpv); break;
case 0x53: tmpv = ssp->RAM[op & 0x1ff]; OP_ANDA(tmpv); break; case 0x53: tmpv = ssp->mem.RAM[op & 0x1ff]; OP_ANDA(tmpv); break;
case 0x63: tmpv = ssp->RAM[op & 0x1ff]; OP_ORA (tmpv); break; case 0x63: tmpv = ssp->mem.RAM[op & 0x1ff]; OP_ORA (tmpv); break;
case 0x73: tmpv = ssp->RAM[op & 0x1ff]; OP_EORA(tmpv); break; case 0x73: tmpv = ssp->mem.RAM[op & 0x1ff]; OP_EORA(tmpv); break;
// OP a, imm /* OP a, imm */
case 0x14: tmpv = *PC++; OP_SUBA(tmpv); break; case 0x14: tmpv = *PC++; OP_SUBA(tmpv); break;
case 0x34: tmpv = *PC++; OP_CMPA(tmpv); break; case 0x34: tmpv = *PC++; OP_CMPA(tmpv); break;
case 0x44: tmpv = *PC++; OP_ADDA(tmpv); break; case 0x44: tmpv = *PC++; OP_ADDA(tmpv); break;
@ -1259,7 +1258,7 @@ void ssp1601_run(int cycles)
case 0x64: tmpv = *PC++; OP_ORA (tmpv); break; case 0x64: tmpv = *PC++; OP_ORA (tmpv); break;
case 0x74: tmpv = *PC++; OP_EORA(tmpv); break; case 0x74: tmpv = *PC++; OP_EORA(tmpv); break;
// OP a, ((ri)) /* OP a, ((ri)) */
case 0x15: tmpv = ptr2_read(op); OP_SUBA(tmpv); break; case 0x15: tmpv = ptr2_read(op); OP_SUBA(tmpv); break;
case 0x35: tmpv = ptr2_read(op); OP_CMPA(tmpv); break; case 0x35: tmpv = ptr2_read(op); OP_CMPA(tmpv); break;
case 0x45: tmpv = ptr2_read(op); OP_ADDA(tmpv); break; case 0x45: tmpv = ptr2_read(op); OP_ADDA(tmpv); break;
@ -1267,7 +1266,7 @@ void ssp1601_run(int cycles)
case 0x65: tmpv = ptr2_read(op); OP_ORA (tmpv); break; case 0x65: tmpv = ptr2_read(op); OP_ORA (tmpv); break;
case 0x75: tmpv = ptr2_read(op); OP_EORA(tmpv); break; case 0x75: tmpv = ptr2_read(op); OP_EORA(tmpv); break;
// OP a, ri /* OP a, ri */
case 0x19: tmpv = rIJ[IJind]; OP_SUBA(tmpv); break; case 0x19: tmpv = rIJ[IJind]; OP_SUBA(tmpv); break;
case 0x39: tmpv = rIJ[IJind]; OP_CMPA(tmpv); break; case 0x39: tmpv = rIJ[IJind]; OP_CMPA(tmpv); break;
case 0x49: tmpv = rIJ[IJind]; OP_ADDA(tmpv); break; case 0x49: tmpv = rIJ[IJind]; OP_ADDA(tmpv); break;
@ -1275,7 +1274,7 @@ void ssp1601_run(int cycles)
case 0x69: tmpv = rIJ[IJind]; OP_ORA (tmpv); break; case 0x69: tmpv = rIJ[IJind]; OP_ORA (tmpv); break;
case 0x79: tmpv = rIJ[IJind]; OP_EORA(tmpv); break; case 0x79: tmpv = rIJ[IJind]; OP_EORA(tmpv); break;
// OP simm /* OP simm */
case 0x1c: case 0x1c:
OP_SUBA(op & 0xff); OP_SUBA(op & 0xff);
#ifdef LOG_SVP #ifdef LOG_SVP
@ -1294,7 +1293,7 @@ void ssp1601_run(int cycles)
if (op&0x100) elprintf(EL_SVP|EL_ANOMALY, "FIXME: simm with upper bit set"); if (op&0x100) elprintf(EL_SVP|EL_ANOMALY, "FIXME: simm with upper bit set");
#endif #endif
break; break;
// MAME code only does LSB of top word, but this looks wrong to me. /* MAME code only does LSB of top word, but this looks wrong to me. */
case 0x5c: case 0x5c:
OP_ANDA(op & 0xff); OP_ANDA(op & 0xff);
#ifdef LOG_SVP #ifdef LOG_SVP
@ -1323,7 +1322,7 @@ void ssp1601_run(int cycles)
} }
while (--g_cycles > 0 && !(ssp->emu_status & SSP_WAIT_MASK)); while (--g_cycles > 0 && !(ssp->emu_status & SSP_WAIT_MASK));
read_P(); // update P read_P(); /* update P */
rPC = GET_PC(); rPC = GET_PC();
#ifdef LOG_SVP #ifdef LOG_SVP

View File

@ -14,12 +14,10 @@
#define _SSP16_H_ #define _SSP16_H_
/* emulation event logging (from Picodrive) */ /* emulation event logging (from Picodrive) */
#ifdef LOG_SVP
#define EL_SVP 0x00004000 /* SVP stuff */ #define EL_SVP 0x00004000 /* SVP stuff */
#define EL_ANOMALY 0x80000000 /* some unexpected conditions (during emulation) */ #define EL_ANOMALY 0x80000000 /* some unexpected conditions (during emulation) */
#ifdef LOG_SVP
#define elprintf(w,f,...) error("%d(%d): " f "\n",frame_count,v_counter,##__VA_ARGS__); #define elprintf(w,f,...) error("%d(%d): " f "\n",frame_count,v_counter,##__VA_ARGS__);
#else
#define elprintf(w,f,...)
#endif #endif
/* register names */ /* register names */
@ -41,37 +39,35 @@ typedef union
unsigned short h; unsigned short h;
unsigned short l; unsigned short l;
#endif #endif
}; } byte;
} ssp_reg_t; } ssp_reg_t;
typedef struct typedef struct
{ {
union { union {
unsigned short RAM[256*2]; // 2 internal RAM banks unsigned short RAM[256*2]; /* 2 internal RAM banks */
struct { struct {
unsigned short RAM0[256]; unsigned short RAM0[256];
unsigned short RAM1[256]; unsigned short RAM1[256];
}; } bank;
}; } mem;
ssp_reg_t gr[16]; // general registers ssp_reg_t gr[16]; /* general registers */
union { union {
unsigned char r[8]; // BANK pointers unsigned char r[8]; /* BANK pointers */
struct { struct {
unsigned char r0[4]; unsigned char r0[4];
unsigned char r1[4]; unsigned char r1[4];
}; } bank;
}; } ptr;
unsigned short stack[6]; unsigned short stack[6];
unsigned int pmac_read[6]; // read modes/addrs for PM0-PM5 unsigned int pmac[2][6]; /* read/write modes/addrs for PM0-PM5 */
unsigned int pmac_write[6]; // write ... #define SSP_PMC_HAVE_ADDR 0x0001 /* address written to PMAC, waiting for mode */
#define SSP_PMC_SET 0x0002 /* PMAC is set */
#define SSP_PMC_HAVE_ADDR 0x0001 // address written to PMAC, waiting for mode #define SSP_HANG 0x1000 /* 68000 hangs SVP */
#define SSP_PMC_SET 0x0002 // PMAC is set #define SSP_WAIT_PM0 0x2000 /* bit1 in PM0 */
#define SSP_HANG 0x1000 // 68000 hangs SVP #define SSP_WAIT_30FE06 0x4000 /* ssp tight loops on 30FE08 to become non-zero */
#define SSP_WAIT_PM0 0x2000 // bit1 in PM0 #define SSP_WAIT_30FE08 0x8000 /* same for 30FE06 */
#define SSP_WAIT_30FE06 0x4000 // ssp tight loops on 30FE08 to become non-zero #define SSP_WAIT_MASK 0xf000
#define SSP_WAIT_30FE08 0x8000 // same for 30FE06
#define SSP_WAIT_MASK 0xf000
unsigned int emu_status; unsigned int emu_status;
unsigned int pad[30]; unsigned int pad[30];
} ssp1601_t; } ssp1601_t;

View File

@ -13,7 +13,6 @@
#include "shared.h" #include "shared.h"
svp_t *svp = NULL; svp_t *svp = NULL;
int16 SVP_cycles = 800;
void svp_init(void) void svp_init(void)
{ {

View File

@ -17,13 +17,12 @@
#include "ssp16.h" #include "ssp16.h"
typedef struct { typedef struct {
unsigned char iram_rom[0x20000]; // IRAM (0-0x7ff) and program ROM (0x800-0x1ffff) unsigned char iram_rom[0x20000]; /* IRAM (0-0x7ff) and program ROM (0x800-0x1ffff) */
unsigned char dram[0x20000]; unsigned char dram[0x20000];
ssp1601_t ssp1601; ssp1601_t ssp1601;
} svp_t; } svp_t;
extern svp_t *svp; extern svp_t *svp;
extern int16 SVP_cycles;
extern void svp_init(void); extern void svp_init(void);
extern void svp_reset(void); extern void svp_reset(void);

View File

@ -47,7 +47,7 @@ uint8 zram[0x2000]; /* Z80 RAM */
uint32 zbank; /* Z80 bank window address */ uint32 zbank; /* Z80 bank window address */
uint8 zstate; /* Z80 bus state (d0 = BUSACK, d1 = /RESET) */ uint8 zstate; /* Z80 bus state (d0 = BUSACK, d1 = /RESET) */
uint8 pico_current; /* PICO current page */ uint8 pico_current; /* PICO current page */
uint8 pico_page[7]; /* PICO page registers */ uint8 pico_regs[7]; /* PICO page registers */
static uint8 tmss[4]; /* TMSS security register */ static uint8 tmss[4]; /* TMSS security register */

View File

@ -49,7 +49,7 @@ extern uint8 zram[0x2000];
extern uint32 zbank; extern uint32 zbank;
extern uint8 zstate; extern uint8 zstate;
extern uint8 pico_current; extern uint8 pico_current;
extern uint8 pico_page[7]; extern uint8 pico_regs[7];
/* Function prototypes */ /* Function prototypes */
extern void gen_init(void); extern void gen_init(void);

View File

@ -42,7 +42,6 @@
#define _FILEIO_H_ #define _FILEIO_H_
/* Function prototypes */ /* Function prototypes */
void get_zipfilename(char *filename);
int load_archive(char *filename); int load_archive(char *filename);
#endif /* _FILEIO_H_ */ #endif /* _FILEIO_H_ */

View File

@ -51,13 +51,10 @@ void activator_reset(int index)
activator[index].Counter = 0; activator[index].Counter = 0;
} }
static inline unsigned char activator_read(int port) static __inline__ unsigned char activator_read(int port)
{ {
/* IR sensors 1-16 data (active low) */ /* IR sensors 1-16 data (active low) */
uint16 data = ~input.pad[port]; uint16 data = ~input.pad[port << 2];
/* Device index */
port = port >> 2;
/* D1 = D0 (data is ready) */ /* D1 = D0 (data is ready) */
uint8 temp = (activator[port].State & 0x01) << 1; uint8 temp = (activator[port].State & 0x01) << 1;
@ -88,7 +85,7 @@ static inline unsigned char activator_read(int port)
return temp; return temp;
} }
static inline void activator_write(int index, unsigned char data, unsigned char mask) static __inline__ void activator_write(int index, unsigned char data, unsigned char mask)
{ {
/* update bits set as output only */ /* update bits set as output only */
data = (activator[index].State & ~mask) | (data & mask); data = (activator[index].State & ~mask) | (data & mask);
@ -123,7 +120,7 @@ unsigned char activator_1_read(void)
unsigned char activator_2_read(void) unsigned char activator_2_read(void)
{ {
return activator_read(4); return activator_read(1);
} }
void activator_1_write(unsigned char data, unsigned char mask) void activator_1_write(unsigned char data, unsigned char mask)

View File

@ -71,7 +71,7 @@ void gamepad_refresh(int port)
} }
} }
static inline unsigned char gamepad_read(int port) static __inline__ unsigned char gamepad_read(int port)
{ {
/* bit 7 is latched, returns current TH state */ /* bit 7 is latched, returns current TH state */
unsigned int data = (gamepad[port].State & 0x40) | 0x3F; unsigned int data = (gamepad[port].State & 0x40) | 0x3F;
@ -142,7 +142,7 @@ static inline unsigned char gamepad_read(int port)
return data; return data;
} }
static inline void gamepad_write(int port, unsigned char data, unsigned char mask) static __inline__ void gamepad_write(int port, unsigned char data, unsigned char mask)
{ {
/* update bits set as output only */ /* update bits set as output only */
data = (gamepad[port].State & ~mask) | (data & mask); data = (gamepad[port].State & ~mask) | (data & mask);

View File

@ -140,7 +140,7 @@ void lightgun_refresh(int port)
/* Sega Phaser */ /* Sega Phaser */
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
static inline unsigned char phaser_read(int port) static __inline__ unsigned char phaser_read(int port)
{ {
/* TL returns TRIGGER (INPUT_A) button status (active low) */ /* TL returns TRIGGER (INPUT_A) button status (active low) */
unsigned char temp = ~((input.pad[port] >> 2) & 0x10); unsigned char temp = ~((input.pad[port] >> 2) & 0x10);

View File

@ -49,7 +49,7 @@ void paddle_reset(int index)
paddle[index].State = 0x40; paddle[index].State = 0x40;
} }
static inline unsigned char paddle_read(int port) static __inline__ unsigned char paddle_read(int port)
{ {
/* FIRE button status (active low) */ /* FIRE button status (active low) */
unsigned char temp = ~(input.pad[port] & 0x10); unsigned char temp = ~(input.pad[port] & 0x10);
@ -83,7 +83,7 @@ static inline unsigned char paddle_read(int port)
return temp; return temp;
} }
static inline void paddle_write(int index, unsigned char data, unsigned char mask) static __inline__ void paddle_write(int index, unsigned char data, unsigned char mask)
{ {
/* update bits set as output only */ /* update bits set as output only */
paddle[index].State = (paddle[index].State & ~mask) | (data & mask); paddle[index].State = (paddle[index].State & ~mask) | (data & mask);

View File

@ -52,7 +52,7 @@ void sportspad_reset(int index)
sportspad[index].Counter = 0; sportspad[index].Counter = 0;
} }
static inline unsigned char sportspad_read(int port) static __inline__ unsigned char sportspad_read(int port)
{ {
/* Buttons 1(B) & 2(C) status (active low) */ /* Buttons 1(B) & 2(C) status (active low) */
unsigned char temp = ~(input.pad[port] & 0x30); unsigned char temp = ~(input.pad[port] & 0x30);
@ -98,7 +98,7 @@ static inline unsigned char sportspad_read(int port)
return temp; return temp;
} }
static inline void sportspad_write(int index, unsigned char data, unsigned char mask) static __inline__ void sportspad_write(int index, unsigned char data, unsigned char mask)
{ {
/* update bits set as output only */ /* update bits set as output only */
data = (sportspad[index].State & ~mask) | (data & mask); data = (sportspad[index].State & ~mask) | (data & mask);

View File

@ -80,7 +80,7 @@ void teamplayer_reset(int port)
teamplayer[port].Counter = 0; teamplayer[port].Counter = 0;
} }
static inline unsigned int teamplayer_read(int port) static __inline__ unsigned int teamplayer_read(int port)
{ {
unsigned int counter = teamplayer[port].Counter; unsigned int counter = teamplayer[port].Counter;
@ -131,7 +131,7 @@ static inline unsigned int teamplayer_read(int port)
} }
} }
static inline void teamplayer_write(int port, unsigned char data, unsigned char mask) static __inline__ void teamplayer_write(int port, unsigned char data, unsigned char mask)
{ {
/* update bits set as output only */ /* update bits set as output only */
unsigned int state = (teamplayer[port].State & ~mask) | (data & mask); unsigned int state = (teamplayer[port].State & ~mask) | (data & mask);

View File

@ -69,6 +69,9 @@ unsigned char xe_a1p_read()
/* Buttons status (active low) */ /* Buttons status (active low) */
uint16 pad = ~input.pad[0]; uint16 pad = ~input.pad[0];
/* Current internal cycle (0-7) */
unsigned int cycle = xe_a1p.Counter & 7;
/* Current 4-bit data cycle */ /* Current 4-bit data cycle */
/* There are eight internal data cycle for each 5 acquisition sequence */ /* There are eight internal data cycle for each 5 acquisition sequence */
/* First 4 return the same 4-bit data, next 4 return next 4-bit data */ /* First 4 return the same 4-bit data, next 4 return next 4-bit data */
@ -104,9 +107,6 @@ unsigned char xe_a1p_read()
break; break;
} }
/* Get current internal cycle (0-7) */
unsigned int cycle = xe_a1p.Counter & 7;
/* TL indicates which part of data is returned (0=1st part, 1=2nd part) */ /* TL indicates which part of data is returned (0=1st part, 1=2nd part) */
temp |= ((cycle & 4) << 2); temp |= ((cycle & 4) << 2);

View File

@ -114,7 +114,7 @@ typedef enum
#endif #endif
/* Convenience registers */ /* Convenience registers */
M68K_REG_IR, /* Instruction register */ M68K_REG_IR /* Instruction register */
} m68k_register_t; } m68k_register_t;

View File

@ -255,9 +255,9 @@ unsigned int ctrl_io_read_byte(unsigned int address)
return m68k_read_bus_8(address); return m68k_read_bus_8(address);
} }
case 0x41: /* OS ROM */ case 0x41: /* BOOT ROM */
{ {
if (address & 1) if ((config.bios & 1) && (address & 1))
{ {
unsigned int data = m68k_read_pcrelative_8(REG_PC) & 0xFE; unsigned int data = m68k_read_pcrelative_8(REG_PC) & 0xFE;
return (gen_bankswitch_r() | data); return (gen_bankswitch_r() | data);
@ -320,13 +320,13 @@ unsigned int ctrl_io_read_word(unsigned int address)
{ {
if ((address & 0xFD) == 0) if ((address & 0xFD) == 0)
{ {
return svp->ssp1601.gr[SSP_XST].h; return svp->ssp1601.gr[SSP_XST].byte.h;
} }
if ((address & 0xFF) == 4) if ((address & 0xFF) == 4)
{ {
unsigned int data = svp->ssp1601.gr[SSP_PM0].h; unsigned int data = svp->ssp1601.gr[SSP_PM0].byte.h;
svp->ssp1601.gr[SSP_PM0].h &= ~1; svp->ssp1601.gr[SSP_PM0].byte.h &= ~1;
return data; return data;
} }
@ -337,7 +337,7 @@ unsigned int ctrl_io_read_word(unsigned int address)
case 0x12: /* RESET */ case 0x12: /* RESET */
case 0x20: /* MEGA-CD */ case 0x20: /* MEGA-CD */
case 0x40: /* TMSS */ case 0x40: /* TMSS */
case 0x41: /* OS ROM */ case 0x41: /* BOOT ROM */
case 0x44: /* RADICA */ case 0x44: /* RADICA */
{ {
return m68k_read_bus_16(address); return m68k_read_bus_16(address);
@ -394,9 +394,9 @@ void ctrl_io_write_byte(unsigned int address, unsigned int data)
return; return;
} }
case 0x41: /* OS ROM */ case 0x41: /* BOOT ROM */
{ {
if (address & 1) if ((config.bios & 1) && (address & 1))
{ {
gen_bankswitch_w(data & 1); gen_bankswitch_w(data & 1);
return; return;
@ -458,7 +458,7 @@ void ctrl_io_write_word(unsigned int address, unsigned int data)
case 0x40: /* TMSS */ case 0x40: /* TMSS */
{ {
if (config.tmss & 1) if (config.bios & 1)
{ {
gen_tmss_w(address & 3, data); gen_tmss_w(address & 3, data);
return; return;
@ -471,8 +471,8 @@ void ctrl_io_write_word(unsigned int address, unsigned int data)
{ {
if (!(address & 0xFD)) if (!(address & 0xFD))
{ {
svp->ssp1601.gr[SSP_XST].h = data; svp->ssp1601.gr[SSP_XST].byte.h = data;
svp->ssp1601.gr[SSP_PM0].h |= 2; svp->ssp1601.gr[SSP_PM0].byte.h |= 2;
svp->ssp1601.emu_status &= ~SSP_WAIT_PM0; svp->ssp1601.emu_status &= ~SSP_WAIT_PM0;
return; return;
} }
@ -482,7 +482,7 @@ void ctrl_io_write_word(unsigned int address, unsigned int data)
case 0x10: /* MEMORY MODE */ case 0x10: /* MEMORY MODE */
case 0x20: /* MEGA-CD */ case 0x20: /* MEGA-CD */
case 0x41: /* OS ROM */ case 0x41: /* BOOT ROM */
case 0x44: /* RADICA */ case 0x44: /* RADICA */
{ {
m68k_unused_16_w (address, data); m68k_unused_16_w (address, data);
@ -727,7 +727,7 @@ unsigned int pico_read_byte(unsigned int address)
case 0x0D: /* PAGE register (TODO) */ case 0x0D: /* PAGE register (TODO) */
{ {
return pico_page[pico_current]; return pico_regs[pico_current];
} }
case 0x10: /* PCM registers (TODO) */ case 0x10: /* PCM registers (TODO) */

View File

@ -55,7 +55,7 @@ unsigned int zbank_unused_r(unsigned int address)
void zbank_unused_w(unsigned int address, unsigned int data) void zbank_unused_w(unsigned int address, unsigned int data)
{ {
#ifdef LOGERROR #ifdef LOGERROR
error("Z80 bank unused write %06X = %02X\n", address, data); error("Z80 bank unused write %06X = %02X (%x)\n", address, data, Z80.pc.d);
#endif #endif
} }

View File

@ -47,14 +47,14 @@
/* machine lock up. */ /* machine lock up. */
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
static inline void z80_unused_w(unsigned int address, unsigned char data) static __inline__ void z80_unused_w(unsigned int address, unsigned char data)
{ {
#ifdef LOGERROR #ifdef LOGERROR
error("Z80 unused write %04X = %02X (%x)\n", address, data, Z80.pc.w.l); error("Z80 unused write %04X = %02X (%x)\n", address, data, Z80.pc.w.l);
#endif #endif
} }
static inline unsigned char z80_unused_r(unsigned int address) static __inline__ unsigned char z80_unused_r(unsigned int address)
{ {
#ifdef LOGERROR #ifdef LOGERROR
error("Z80 unused read %04X (%x)\n", address, Z80.pc.w.l); error("Z80 unused read %04X (%x)\n", address, Z80.pc.w.l);
@ -62,7 +62,7 @@ static inline unsigned char z80_unused_r(unsigned int address)
return 0xFF; return 0xFF;
} }
static inline void z80_lockup_w(unsigned int address, unsigned char data) static __inline__ void z80_lockup_w(unsigned int address, unsigned char data)
{ {
#ifdef LOGERROR #ifdef LOGERROR
error("Z80 lockup write %04X = %02X (%x)\n", address, data, Z80.pc.w.l); error("Z80 lockup write %04X = %02X (%x)\n", address, data, Z80.pc.w.l);
@ -74,7 +74,7 @@ static inline void z80_lockup_w(unsigned int address, unsigned char data)
} }
} }
static inline unsigned char z80_lockup_r(unsigned int address) static __inline__ unsigned char z80_lockup_r(unsigned int address)
{ {
#ifdef LOGERROR #ifdef LOGERROR
error("Z80 lockup read %04X (%x)\n", address, Z80.pc.w.l); error("Z80 lockup read %04X (%x)\n", address, Z80.pc.w.l);
@ -119,12 +119,11 @@ unsigned char z80_memory_r(unsigned int address)
default: /* $8000-$FFFF: 68k bank (32K) */ default: /* $8000-$FFFF: 68k bank (32K) */
{ {
address = zbank | (address & 0x7FFF); address = zbank | (address & 0x7FFF);
unsigned int slot = address >> 16; if (zbank_memory_map[address >> 16].read)
if (zbank_memory_map[slot].read)
{ {
return (*zbank_memory_map[slot].read)(address); return (*zbank_memory_map[address >> 16].read)(address);
} }
return READ_BYTE(m68k_memory_map[slot].base, address & 0xFFFF); return READ_BYTE(m68k_memory_map[address >> 16].base, address & 0xFFFF);
} }
} }
} }
@ -174,13 +173,12 @@ void z80_memory_w(unsigned int address, unsigned char data)
default: /* $8000-$FFFF: 68k bank (32K) */ default: /* $8000-$FFFF: 68k bank (32K) */
{ {
address = zbank | (address & 0x7FFF); address = zbank | (address & 0x7FFF);
unsigned int slot = address >> 16; if (zbank_memory_map[address >> 16].write)
if (zbank_memory_map[slot].write)
{ {
(*zbank_memory_map[slot].write)(address, data); (*zbank_memory_map[address >> 16].write)(address, data);
return; return;
} }
WRITE_BYTE(m68k_memory_map[slot].base, address & 0xFFFF, data); WRITE_BYTE(m68k_memory_map[address >> 16].base, address & 0xFFFF, data);
return; return;
} }
} }

View File

@ -43,9 +43,8 @@ static void gen_sinc(double rolloff, int width, double offset, double spacing, d
double const fstep = M_PI / maxh * spacing; double const fstep = M_PI / maxh * spacing;
double const to_w = maxh * 2 / width; double const to_w = maxh * 2 / width;
double const pow_a_n = pow( rolloff, maxh ); double const pow_a_n = pow( rolloff, maxh );
scale /= maxh * 2;
double angle = (count / 2 - 1 + offset) * -fstep; double angle = (count / 2 - 1 + offset) * -fstep;
scale /= maxh * 2;
do do
{ {
@ -154,10 +153,8 @@ void Fir_Resampler_clear()
double Fir_Resampler_time_ratio( double new_factor, double rolloff ) double Fir_Resampler_time_ratio( double new_factor, double rolloff )
{ {
ratio = new_factor;
int i, r; int i, r;
double nearest, error; double nearest, error, filter;
double fstep = 0.0; double fstep = 0.0;
double least_error = 2; double least_error = 2;
double pos = 0.0; double pos = 0.0;
@ -165,7 +162,7 @@ double Fir_Resampler_time_ratio( double new_factor, double rolloff )
for ( r = 1; r <= MAX_RES; r++ ) for ( r = 1; r <= MAX_RES; r++ )
{ {
pos += ratio; pos += new_factor;
nearest = floor( pos + 0.5 ); nearest = floor( pos + 0.5 );
error = fabs( pos - nearest ); error = fabs( pos - nearest );
if ( error < least_error ) if ( error < least_error )
@ -183,7 +180,7 @@ double Fir_Resampler_time_ratio( double new_factor, double rolloff )
ratio = fstep; ratio = fstep;
fstep = fmod( fstep, 1.0 ); fstep = fmod( fstep, 1.0 );
double filter = (ratio < 1.0) ? 1.0 : 1.0 / ratio; filter = (ratio < 1.0) ? 1.0 : 1.0 / ratio;
pos = 0.0; pos = 0.0;
input_per_cycle = 0; input_per_cycle = 0;
@ -310,9 +307,9 @@ int Fir_Resampler_read( sample_t* out, long count )
imp_phase = res - remain; imp_phase = res - remain;
int left = write_pos - in; n = write_pos - in;
write_pos = &buffer [left]; write_pos = &buffer [n];
memmove( buffer, in, left * sizeof *in ); memmove( buffer, in, n * sizeof *in );
return out - out_; return out - out_;
} }
@ -321,9 +318,9 @@ int Fir_Resampler_read( sample_t* out, long count )
int Fir_Resampler_input_needed( long output_count ) int Fir_Resampler_input_needed( long output_count )
{ {
long input_count = 0; long input_count = 0;
unsigned long skip = skip_bits >> imp_phase; unsigned long skip = skip_bits >> imp_phase;
int remain = res - imp_phase; int remain = res - imp_phase;
while ( (output_count) > 0 ) while ( (output_count) > 0 )
{ {
input_count += step + (skip & 1) * STEREO; input_count += step + (skip & 1) * STEREO;
@ -336,10 +333,10 @@ int Fir_Resampler_input_needed( long output_count )
output_count --; output_count --;
} }
long input_extra = input_count - (write_pos - &buffer [WRITE_OFFSET]); input_count -= (write_pos - &buffer [WRITE_OFFSET]);
if ( input_extra < 0 ) if ( input_count < 0 )
input_extra = 0; input_count = 0;
return (input_extra >> 1); return (input_count >> 1);
} }
int Fir_Resampler_skip_input( long count ) int Fir_Resampler_skip_input( long count )

View File

@ -105,33 +105,19 @@ int blip_samples_avail( const blip_buffer_t* s )
return s->offset >> time_bits; return s->offset >> time_bits;
} }
/* Removes n samples from buffer */ void blip_read_samples( blip_buffer_t* s, short out[], int count)
static void remove_samples( blip_buffer_t* s, int n )
{
int remain = blip_samples_avail( s ) + buf_extra - n;
s->offset -= n * time_unit;
/* Copy remaining samples to beginning of buffer and clear the rest */
memmove( s->buf, &s->buf [n], remain * sizeof (buf_t) );
memset( &s->buf [remain], 0, n * sizeof (buf_t) );
}
int blip_read_samples( blip_buffer_t* s, short out [], int count, int stereo )
{ {
/* can't read more than available */ /* can't read more than available */
int avail = blip_samples_avail( s ); int avail = s->offset >> time_bits;
if ( count > avail ) if ( count > avail )
count = avail; count = avail;
if ( count ) if ( count )
{ {
/* Sum deltas and write out */ /* Sum deltas and write out */
int i; int i, sample;
for ( i = 0; i < count; ++i ) for ( i = 0; i < count; ++i )
{ {
int sample;
/* Apply slight high-pass filter */ /* Apply slight high-pass filter */
s->amp -= s->amp >> 9; s->amp -= s->amp >> 9;
@ -145,11 +131,15 @@ int blip_read_samples( blip_buffer_t* s, short out [], int count, int stereo )
if ( sample < -32768 ) sample = -32768; if ( sample < -32768 ) sample = -32768;
if ( sample > +32767 ) sample = +32767; if ( sample > +32767 ) sample = +32767;
out [i << stereo] = sample; out [i] = sample;
} }
remove_samples( s, count ); /* Copy remaining samples to beginning of buffer and clear the rest */
} i = (s->offset >> time_bits) + buf_extra - count;
memmove( s->buf, &s->buf [count], i * sizeof (buf_t) );
memset( &s->buf [i], 0, count * sizeof (buf_t) );
return count; /* Remove samples */
s->offset -= count * time_unit;
}
} }

View File

@ -39,10 +39,8 @@ void blip_end_frame( blip_buffer_t*, int duration );
int blip_samples_avail( const blip_buffer_t* ); int blip_samples_avail( const blip_buffer_t* );
/* Reads at most n samples out of buffer into out, removing them from from /* Reads at most n samples out of buffer into out, removing them from from
the buffer. Returns number of samples actually read and removed. If stereo is the buffer. */
true, increments 'out' one extra time after writing each sample, to allow void blip_read_samples( blip_buffer_t*, short out [], int n);
easy interleving of two channels into a stereo output buffer. */
int blip_read_samples( blip_buffer_t*, short out [], int n, int stereo );
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -1,4 +1,4 @@
//---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
// //
// 3 Band EQ :) // 3 Band EQ :)
// //
@ -14,9 +14,9 @@
// The author assumes NO RESPONSIBILITY for any problems caused by the use of // The author assumes NO RESPONSIBILITY for any problems caused by the use of
// this software. // this software.
// //
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------*/
// NOTES : /* NOTES :
// //
// - Original filter code by Paul Kellet (musicdsp.pdf) // - Original filter code by Paul Kellet (musicdsp.pdf)
// //
@ -25,71 +25,72 @@
// - Now with P4 Denormal fix :) // - Now with P4 Denormal fix :)
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------*/
// ---------- /* ----------
//| Includes | //| Includes |
// ---------- // ----------*/
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <math.h> #include <math.h>
#include "eq.h" #include "eq.h"
#include "types.h"
// ----------- /* -----------
//| Constants | //| Constants |
// ----------- // -----------*/
static double vsa = (1.0 / 4294967295.0); // Very small amount (Denormal Fix) static double vsa = (1.0 / 4294967295.0); /* Very small amount (Denormal Fix) */
// --------------- /* ---------------
//| Initialise EQ | //| Initialise EQ |
// --------------- // ---------------*/
// Recommended frequencies are ... /* Recommended frequencies are ...
// //
// lowfreq = 880 Hz // lowfreq = 880 Hz
// highfreq = 5000 Hz // highfreq = 5000 Hz
// //
// Set mixfreq to whatever rate your system is using (eg 48Khz) // Set mixfreq to whatever rate your system is using (eg 48Khz)*/
void init_3band_state(EQSTATE * es, int lowfreq, int highfreq, int mixfreq) void init_3band_state(EQSTATE * es, int lowfreq, int highfreq, int mixfreq)
{ {
// Clear state /* Clear state */
memset(es, 0, sizeof(EQSTATE)); memset(es, 0, sizeof(EQSTATE));
// Set Low/Mid/High gains to unity /* Set Low/Mid/High gains to unity */
es->lg = 1.0; es->lg = 1.0;
es->mg = 1.0; es->mg = 1.0;
es->hg = 1.0; es->hg = 1.0;
// Calculate filter cutoff frequencies /* Calculate filter cutoff frequencies */
es->lf = 2 * sin(M_PI * ((double) lowfreq / (double) mixfreq)); es->lf = 2 * sin(M_PI * ((double) lowfreq / (double) mixfreq));
es->hf = 2 * sin(M_PI * ((double) highfreq / (double) mixfreq)); es->hf = 2 * sin(M_PI * ((double) highfreq / (double) mixfreq));
} }
// --------------- /* ---------------
//| EQ one sample | //| EQ one sample |
// --------------- // ---------------*/
// - sample can be any range you like :) /* - sample can be any range you like :)
// //
// Note that the output will depend on the gain settings for each band // Note that the output will depend on the gain settings for each band
// (especially the bass) so may require clipping before output, but you // (especially the bass) so may require clipping before output, but you
// knew that anyway :) // knew that anyway :)*/
double do_3band(EQSTATE * es, int sample) double do_3band(EQSTATE * es, int sample)
{ {
// Locals /* Locals */
double l, m, h; // Low / Mid / High - Sample Values double l, m, h; /* Low / Mid / High - Sample Values */
// Filter #1 (lowpass) /* Filter #1 (lowpass) */
es->f1p0 += (es->lf * ((double) sample - es->f1p0)) + vsa; es->f1p0 += (es->lf * ((double) sample - es->f1p0)) + vsa;
es->f1p1 += (es->lf * (es->f1p0 - es->f1p1)); es->f1p1 += (es->lf * (es->f1p0 - es->f1p1));
@ -98,7 +99,7 @@ double do_3band(EQSTATE * es, int sample)
l = es->f1p3; l = es->f1p3;
// Filter #2 (highpass) /* Filter #2 (highpass) */
es->f2p0 += (es->hf * ((double) sample - es->f2p0)) + vsa; es->f2p0 += (es->hf * ((double) sample - es->f2p0)) + vsa;
es->f2p1 += (es->hf * (es->f2p0 - es->f2p1)); es->f2p1 += (es->hf * (es->f2p0 - es->f2p1));
@ -107,25 +108,25 @@ double do_3band(EQSTATE * es, int sample)
h = es->sdm3 - es->f2p3; h = es->sdm3 - es->f2p3;
// Calculate midrange (signal - (low + high)) /* Calculate midrange (signal - (low + high)) */
//m = es->sdm3 - (h + l); /* m = es->sdm3 - (h + l); */
// fix from http://www.musicdsp.org/showArchiveComment.php?ArchiveID=236 ? /* fix from http://www.musicdsp.org/showArchiveComment.php?ArchiveID=236 ? */
m = sample - (h + l); m = sample - (h + l);
// Scale, Combine and store /* Scale, Combine and store */
l *= es->lg; l *= es->lg;
m *= es->mg; m *= es->mg;
h *= es->hg; h *= es->hg;
// Shuffle history buffer /* Shuffle history buffer */
es->sdm3 = es->sdm2; es->sdm3 = es->sdm2;
es->sdm2 = es->sdm1; es->sdm2 = es->sdm1;
es->sdm1 = sample; es->sdm1 = sample;
// Return result /* Return result */
return (int) (l + m + h); return (int) (l + m + h);
} }

View File

@ -1,4 +1,4 @@
//--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
// //
// 3 Band EQ :) // 3 Band EQ :)
// //
@ -14,54 +14,54 @@
// The author assumes NO RESPONSIBILITY for any problems caused by the use of // The author assumes NO RESPONSIBILITY for any problems caused by the use of
// this software. // this software.
// //
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------*/
#ifndef __EQ3BAND__ #ifndef __EQ3BAND__
#define __EQ3BAND__ #define __EQ3BAND__
// ------------ /* ------------
//| Structures | //| Structures |
// ------------ // ------------*/
typedef struct { typedef struct {
// Filter #1 (Low band) /* Filter #1 (Low band) */
double lf; // Frequency double lf; /* Frequency */
double f1p0; // Poles ... double f1p0; /* Poles ... */
double f1p1; double f1p1;
double f1p2; double f1p2;
double f1p3; double f1p3;
// Filter #2 (High band) /* Filter #2 (High band) */
double hf; // Frequency double hf; /* Frequency */
double f2p0; // Poles ... double f2p0; /* Poles ... */
double f2p1; double f2p1;
double f2p2; double f2p2;
double f2p3; double f2p3;
// Sample history buffer /* Sample history buffer */
double sdm1; // Sample data minus 1 double sdm1; /* Sample data minus 1 */
double sdm2; // 2 double sdm2; /* 2 */
double sdm3; // 3 double sdm3; /* 3 */
// Gain Controls /* Gain Controls */
double lg; // low gain double lg; /* low gain */
double mg; // mid gain double mg; /* mid gain */
double hg; // high gain double hg; /* high gain */
} EQSTATE; } EQSTATE;
// --------- /* ---------
//| Exports | //| Exports |
// --------- // ---------*/
extern void init_3band_state(EQSTATE * es, int lowfreq, int highfreq, extern void init_3band_state(EQSTATE * es, int lowfreq, int highfreq,
int mixfreq); int mixfreq);
extern double do_3band(EQSTATE * es, int sample); extern double do_3band(EQSTATE * es, int sample);
#endif // #ifndef __EQ3BAND__ #endif /* #ifndef __EQ3BAND__ */

View File

@ -165,9 +165,7 @@ void SN76489_Write(int data)
SN76489.LatchedRegister = (data >> 4) & 0x07; SN76489.LatchedRegister = (data >> 4) & 0x07;
} }
int LatchedRegister = SN76489.LatchedRegister; switch (SN76489.LatchedRegister)
switch (LatchedRegister)
{ {
case 0: case 0:
case 2: case 2:
@ -175,22 +173,22 @@ void SN76489_Write(int data)
if (data & 0x80) if (data & 0x80)
{ {
/* Data byte %1 cc t dddd */ /* Data byte %1 cc t dddd */
SN76489.Registers[LatchedRegister] = (SN76489.Registers[LatchedRegister] & 0x3f0) | (data & 0xf); SN76489.Registers[SN76489.LatchedRegister] = (SN76489.Registers[SN76489.LatchedRegister] & 0x3f0) | (data & 0xf);
} }
else else
{ {
/* Data byte %0 - dddddd */ /* Data byte %0 - dddddd */
SN76489.Registers[LatchedRegister] = (SN76489.Registers[LatchedRegister] & 0x00f) | ((data & 0x3f) << 4); SN76489.Registers[SN76489.LatchedRegister] = (SN76489.Registers[SN76489.LatchedRegister] & 0x00f) | ((data & 0x3f) << 4);
} }
/* Zero frequency changed to 1 to avoid div/0 */ /* Zero frequency changed to 1 to avoid div/0 */
if (SN76489.Registers[LatchedRegister] == 0) SN76489.Registers[LatchedRegister] = 1; if (SN76489.Registers[SN76489.LatchedRegister] == 0) SN76489.Registers[SN76489.LatchedRegister] = 1;
break; break;
case 1: case 1:
case 3: case 3:
case 5: /* Channel attenuation */ case 5: /* Channel attenuation */
SN76489.Registers[LatchedRegister] = data & 0x0f; SN76489.Registers[SN76489.LatchedRegister] = data & 0x0f;
SN76489.Channels[LatchedRegister>>1] = PSGVolumeValues[data&0x0f]; SN76489.Channels[SN76489.LatchedRegister>>1] = PSGVolumeValues[data&0x0f];
break; break;
case 6: /* Noise control */ case 6: /* Noise control */
@ -327,5 +325,5 @@ void SN76489_Update(INT16 *buffer, int length)
/* Read samples into output buffer */ /* Read samples into output buffer */
blip_end_frame(blip, clock_length); blip_end_frame(blip, clock_length);
blip_read_samples(blip, buffer, length, 0); blip_read_samples(blip, buffer, length);
} }

View File

@ -464,34 +464,34 @@ static const INT8 lfo_pm_table[8*8] = {
static unsigned char table[19][8] = { static unsigned char table[19][8] = {
/* MULT MULT modTL DcDmFb AR/DR AR/DR SL/RR SL/RR */ /* MULT MULT modTL DcDmFb AR/DR AR/DR SL/RR SL/RR */
/* 0 1 2 3 4 5 6 7 */ /* 0 1 2 3 4 5 6 7 */
{0x49, 0x4c, 0x4c, 0x12, 0x00, 0x00, 0x00, 0x00 }, //0 {0x49, 0x4c, 0x4c, 0x12, 0x00, 0x00, 0x00, 0x00 }, /* 0 */
{0x61, 0x61, 0x1e, 0x17, 0xf0, 0x78, 0x00, 0x17 }, //1 {0x61, 0x61, 0x1e, 0x17, 0xf0, 0x78, 0x00, 0x17 }, /* 1 */
{0x13, 0x41, 0x1e, 0x0d, 0xd7, 0xf7, 0x13, 0x13 }, //2 {0x13, 0x41, 0x1e, 0x0d, 0xd7, 0xf7, 0x13, 0x13 }, /* 2 */
{0x13, 0x01, 0x99, 0x04, 0xf2, 0xf4, 0x11, 0x23 }, //3 {0x13, 0x01, 0x99, 0x04, 0xf2, 0xf4, 0x11, 0x23 }, /* 3 */
{0x21, 0x61, 0x1b, 0x07, 0xaf, 0x64, 0x40, 0x27 }, //4 {0x21, 0x61, 0x1b, 0x07, 0xaf, 0x64, 0x40, 0x27 }, /* 4 */
//{0x22, 0x21, 0x1e, 0x09, 0xf0, 0x76, 0x08, 0x28 }, //5 /*{0x22, 0x21, 0x1e, 0x09, 0xf0, 0x76, 0x08, 0x28 }, */ /* 5 */
{0x22, 0x21, 0x1e, 0x06, 0xf0, 0x75, 0x08, 0x18 }, //5 {0x22, 0x21, 0x1e, 0x06, 0xf0, 0x75, 0x08, 0x18 }, /* 5 */
//{0x31, 0x22, 0x16, 0x09, 0x90, 0x7f, 0x00, 0x08 }, //6 /*{0x31, 0x22, 0x16, 0x09, 0x90, 0x7f, 0x00, 0x08 }, */ /* 6 */
{0x31, 0x22, 0x16, 0x05, 0x90, 0x71, 0x00, 0x13 }, //6 {0x31, 0x22, 0x16, 0x05, 0x90, 0x71, 0x00, 0x13 }, /* 6 */
{0x21, 0x61, 0x1d, 0x07, 0x82, 0x80, 0x10, 0x17 }, //7 {0x21, 0x61, 0x1d, 0x07, 0x82, 0x80, 0x10, 0x17 }, /* 7 */
{0x23, 0x21, 0x2d, 0x16, 0xc0, 0x70, 0x07, 0x07 }, //8 {0x23, 0x21, 0x2d, 0x16, 0xc0, 0x70, 0x07, 0x07 }, /* 8 */
{0x61, 0x61, 0x1b, 0x06, 0x64, 0x65, 0x10, 0x17 }, //9 {0x61, 0x61, 0x1b, 0x06, 0x64, 0x65, 0x10, 0x17 }, /* 9 */
//{0x61, 0x61, 0x0c, 0x08, 0x85, 0xa0, 0x79, 0x07 }, //A /* {0x61, 0x61, 0x0c, 0x08, 0x85, 0xa0, 0x79, 0x07 }, */ /* A */
{0x61, 0x61, 0x0c, 0x18, 0x85, 0xf0, 0x70, 0x07 }, //A {0x61, 0x61, 0x0c, 0x18, 0x85, 0xf0, 0x70, 0x07 }, /* A */
{0x23, 0x01, 0x07, 0x11, 0xf0, 0xa4, 0x00, 0x22 }, //B {0x23, 0x01, 0x07, 0x11, 0xf0, 0xa4, 0x00, 0x22 }, /* B */
{0x97, 0xc1, 0x24, 0x07, 0xff, 0xf8, 0x22, 0x12 }, //C {0x97, 0xc1, 0x24, 0x07, 0xff, 0xf8, 0x22, 0x12 }, /* C */
//{0x61, 0x10, 0x0c, 0x08, 0xf2, 0xc4, 0x40, 0xc8 }, //D /* {0x61, 0x10, 0x0c, 0x08, 0xf2, 0xc4, 0x40, 0xc8 }, */ /* D */
{0x61, 0x10, 0x0c, 0x05, 0xf2, 0xf4, 0x40, 0x44 }, //D {0x61, 0x10, 0x0c, 0x05, 0xf2, 0xf4, 0x40, 0x44 }, /* D */
{0x01, 0x01, 0x55, 0x03, 0xf3, 0x92, 0xf3, 0xf3 }, //E {0x01, 0x01, 0x55, 0x03, 0xf3, 0x92, 0xf3, 0xf3 }, /* E */
{0x61, 0x41, 0x89, 0x03, 0xf1, 0xf4, 0xf0, 0x13 }, //F {0x61, 0x41, 0x89, 0x03, 0xf1, 0xf4, 0xf0, 0x13 }, /* F */
/* drum instruments definitions */ /* drum instruments definitions */
/* MULTI MULTI modTL xxx AR/DR AR/DR SL/RR SL/RR */ /* MULTI MULTI modTL xxx AR/DR AR/DR SL/RR SL/RR */
@ -886,16 +886,16 @@ INLINE void rhythm_calc( YM2413_OPLL_CH *CH, unsigned int noise )
/* Phase generation is based on: */ /* Phase generation is based on: */
// HH (13) channel 7->slot 1 combined with channel 8->slot 2 (same combination as TOP CYMBAL but different output phases) /* HH (13) channel 7->slot 1 combined with channel 8->slot 2 (same combination as TOP CYMBAL but different output phases) */
// SD (16) channel 7->slot 1 /* SD (16) channel 7->slot 1 */
// TOM (14) channel 8->slot 1 /* TOM (14) channel 8->slot 1 */
// TOP (17) channel 7->slot 1 combined with channel 8->slot 2 (same combination as HIGH HAT but different output phases) /* TOP (17) channel 7->slot 1 combined with channel 8->slot 2 (same combination as HIGH HAT but different output phases) */
/* Envelope generation based on: */ /* Envelope generation based on: */
// HH channel 7->slot1 /* HH channel 7->slot1 */
// SD channel 7->slot2 /* SD channel 7->slot2 */
// TOM channel 8->slot1 /* TOM channel 8->slot1 */
// TOP channel 8->slot2 /* TOP channel 8->slot2 */
/* The following formulas can be well optimized. /* The following formulas can be well optimized.
@ -1219,12 +1219,10 @@ INLINE void set_ksl_wave_fb(int chan,int v)
/*carrier*/ /*carrier*/
SLOT = &CH->SLOT[SLOT2]; SLOT = &CH->SLOT[SLOT2];
int ksl = v>>6; /* 0 / 1.5 / 3.0 / 6.0 dB/OCT */
SLOT->ksl = ksl ? 3-ksl : 31;
SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl);
SLOT->wavetable = ((v&0x10)>>4)*SIN_LEN; SLOT->wavetable = ((v&0x10)>>4)*SIN_LEN;
v >>= 6; /* 0 / 1.5 / 3.0 / 6.0 dB/OCT */
SLOT->ksl = v ? 3-v : 31;
SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl);
} }
/* set attack rate & decay rate */ /* set attack rate & decay rate */
@ -1533,6 +1531,7 @@ static void OPLLWriteReg(int r, int v)
/* update */ /* update */
if(CH->block_fnum != block_fnum) if(CH->block_fnum != block_fnum)
{ {
UINT8 block;
CH->block_fnum = block_fnum; CH->block_fnum = block_fnum;
/* BLK 2,1,0 bits -> bits 3,2,1 of kcode, FNUM MSB -> kcode LSB */ /* BLK 2,1,0 bits -> bits 3,2,1 of kcode, FNUM MSB -> kcode LSB */
@ -1541,7 +1540,7 @@ static void OPLLWriteReg(int r, int v)
CH->ksl_base = ksl_tab[block_fnum>>5]; CH->ksl_base = ksl_tab[block_fnum>>5];
block_fnum = block_fnum * 2; block_fnum = block_fnum * 2;
UINT8 block = (block_fnum&0x1c00) >> 10; block = (block_fnum&0x1c00) >> 10;
CH->fc = ym2413.fn_tab[block_fnum&0x03ff] >> (7-block); CH->fc = ym2413.fn_tab[block_fnum&0x03ff] >> (7-block);
/* refresh Total Level in both SLOTs of this channel */ /* refresh Total Level in both SLOTs of this channel */

View File

@ -244,7 +244,7 @@ O( 0),O( 1),O( 2),O( 3),
O( 0),O( 1),O( 2),O( 3), O( 0),O( 1),O( 2),O( 3),
*/ */
O(18),O(18),O( 0),O( 0), O(18),O(18),O( 0),O( 0),
O( 0),O( 0),O( 2),O( 2), // Nemesis's tests O( 0),O( 0),O( 2),O( 2), /* Nemesis's tests */
O( 0),O( 1),O( 2),O( 3), O( 0),O( 1),O( 2),O( 3),
O( 0),O( 1),O( 2),O( 3), O( 0),O( 1),O( 2),O( 3),
@ -986,9 +986,9 @@ INLINE void set_ar_ksr(FM_CH *CH,FM_SLOT *SLOT,int v)
} }
/* Even if it seems unnecessary to do it here, it could happen that KSR and KC */ /* Even if it seems unnecessary to do it here, it could happen that KSR and KC */
/* but the resulted SLOT->ksr value (kc >> SLOT->KSR) remains unchanged. */ /* are modified but the resulted SLOT->ksr value (kc >> SLOT->KSR) remains unchanged. */
/* In such case, Attack Rate would not be recalculated by "refresh_fc_eg_slot". */ /* In such case, Attack Rate would not be recalculated by "refresh_fc_eg_slot". */
/* This fixes the intro of "The Adventures of Batman & Robin" (Eke-Eke) */ /* This actually fixes the intro of "The Adventures of Batman & Robin" (Eke-Eke) */
if ((SLOT->ar + SLOT->ksr) < (32+62)) if ((SLOT->ar + SLOT->ksr) < (32+62))
{ {
SLOT->eg_sh_ar = eg_rate_shift [SLOT->ar + SLOT->ksr ]; SLOT->eg_sh_ar = eg_rate_shift [SLOT->ar + SLOT->ksr ];
@ -1287,16 +1287,18 @@ INLINE void update_phase_lfo_slot(FM_SLOT *SLOT , INT32 pms, UINT32 block_fnum)
if (lfo_fn_table_index_offset) /* LFO phase modulation active */ if (lfo_fn_table_index_offset) /* LFO phase modulation active */
{ {
block_fnum = block_fnum*2 + lfo_fn_table_index_offset; UINT8 blk;
int kc, fc;
UINT8 blk = (block_fnum&0x7000) >> 12; block_fnum = block_fnum*2 + lfo_fn_table_index_offset;
blk = (block_fnum&0x7000) >> 12;
block_fnum = block_fnum & 0xfff; block_fnum = block_fnum & 0xfff;
/* keyscale code */ /* keyscale code */
int kc = (blk<<2) | opn_fktable[block_fnum >> 8]; kc = (blk<<2) | opn_fktable[block_fnum >> 8];
/* (frequency) phase increment counter */ /* (frequency) phase increment counter */
int fc = (ym2612.OPN.fn_table[block_fnum]>>(7-blk)) + SLOT->DT[kc]; fc = (ym2612.OPN.fn_table[block_fnum]>>(7-blk)) + SLOT->DT[kc];
/* (frequency) phase overflow (credits to Nemesis) */ /* (frequency) phase overflow (credits to Nemesis) */
if (fc < 0) fc += ym2612.OPN.fn_max; if (fc < 0) fc += ym2612.OPN.fn_max;
@ -1318,19 +1320,21 @@ INLINE void update_phase_lfo_channel(FM_CH *CH)
if (lfo_fn_table_index_offset) /* LFO phase modulation active */ if (lfo_fn_table_index_offset) /* LFO phase modulation active */
{ {
block_fnum = block_fnum*2 + lfo_fn_table_index_offset; UINT8 blk;
int kc, fc, finc;
UINT8 blk = (block_fnum&0x7000) >> 12; block_fnum = block_fnum*2 + lfo_fn_table_index_offset;
blk = (block_fnum&0x7000) >> 12;
block_fnum = block_fnum & 0xfff; block_fnum = block_fnum & 0xfff;
/* keyscale code */ /* keyscale code */
int kc = (blk<<2) | opn_fktable[block_fnum >> 8]; kc = (blk<<2) | opn_fktable[block_fnum >> 8];
/* (frequency) phase increment counter */ /* (frequency) phase increment counter */
int fc = (ym2612.OPN.fn_table[block_fnum]>>(7-blk)); fc = (ym2612.OPN.fn_table[block_fnum]>>(7-blk));
/* (frequency) phase overflow (credits to Nemesis) */ /* (frequency) phase overflow (credits to Nemesis) */
int finc = fc + CH->SLOT[SLOT1].DT[kc]; finc = fc + CH->SLOT[SLOT1].DT[kc];
if (finc < 0) finc += ym2612.OPN.fn_max; if (finc < 0) finc += ym2612.OPN.fn_max;
CH->SLOT[SLOT1].phase += (finc*CH->SLOT[SLOT1].mul) >> 1; CH->SLOT[SLOT1].phase += (finc*CH->SLOT[SLOT1].mul) >> 1;
@ -1435,12 +1439,11 @@ INLINE signed int op_calc1(UINT32 phase, unsigned int env, signed int pm)
INLINE void chan_calc(FM_CH *CH) INLINE void chan_calc(FM_CH *CH)
{ {
UINT32 AM = ym2612.OPN.LFO_AM >> CH->ams; UINT32 AM = ym2612.OPN.LFO_AM >> CH->ams;
unsigned int eg_out = volume_calc(&CH->SLOT[SLOT1]);
m2 = c1 = c2 = mem = 0; m2 = c1 = c2 = mem = 0;
*CH->mem_connect = CH->mem_value; /* restore delayed sample (MEM) value to m2 or c2 */ *CH->mem_connect = CH->mem_value; /* restore delayed sample (MEM) value to m2 or c2 */
unsigned int eg_out = volume_calc(&CH->SLOT[SLOT1]);
{ {
INT32 out = CH->op1_out[0] + CH->op1_out[1]; INT32 out = CH->op1_out[0] + CH->op1_out[1];
CH->op1_out[0] = CH->op1_out[1]; CH->op1_out[0] = CH->op1_out[1];
@ -1720,7 +1723,7 @@ INLINE void OPNWriteReg(int r, int v)
ym2612.OPN.SL3.kcode[c]= (blk<<2) | opn_fktable[fn >> 7]; ym2612.OPN.SL3.kcode[c]= (blk<<2) | opn_fktable[fn >> 7];
/* phase increment counter */ /* phase increment counter */
ym2612.OPN.SL3.fc[c] = ym2612.OPN.fn_table[fn*2]>>(7-blk); ym2612.OPN.SL3.fc[c] = ym2612.OPN.fn_table[fn*2]>>(7-blk);
ym2612.OPN.SL3.block_fnum[c] = (blk<<11) | fn; //fn; ym2612.OPN.SL3.block_fnum[c] = (blk<<11) | fn;
ym2612.CH[2].SLOT[SLOT1].Incr=-1; ym2612.CH[2].SLOT[SLOT1].Incr=-1;
} }
break; break;
@ -2136,7 +2139,7 @@ void YM2612Update(int *buffer, int length)
if (out_fm[5] > 8192) out_fm[5] = 8192; if (out_fm[5] > 8192) out_fm[5] = 8192;
else if (out_fm[5] < -8192) out_fm[5] = -8192; else if (out_fm[5] < -8192) out_fm[5] = -8192;
/* 6-channels mixing */ /* 6-channels stereo mixing */
lt = ((out_fm[0]) & ym2612.OPN.pan[0]); lt = ((out_fm[0]) & ym2612.OPN.pan[0]);
rt = ((out_fm[0]) & ym2612.OPN.pan[1]); rt = ((out_fm[0]) & ym2612.OPN.pan[1]);
lt += ((out_fm[1]) & ym2612.OPN.pan[2]); lt += ((out_fm[1]) & ym2612.OPN.pan[2]);
@ -2215,14 +2218,13 @@ void YM2612Restore(unsigned char *buffer)
int YM2612LoadContext(unsigned char *state) int YM2612LoadContext(unsigned char *state)
{ {
int c,s;
uint8 index;
int bufferptr = sizeof(YM2612); int bufferptr = sizeof(YM2612);
/* restore YM2612 context */ /* restore YM2612 context */
YM2612Restore(state); YM2612Restore(state);
int c,s;
uint8 index;
/* restore DT table address pointer for each channel slots */ /* restore DT table address pointer for each channel slots */
for( c = 0 ; c < 6 ; c++ ) for( c = 0 ; c < 6 ; c++ )
{ {

View File

@ -1,6 +1,9 @@
#undef uint8 #undef uint8
#undef uint16 #undef uint16
#undef uint32 #undef uint32
#undef int8
#undef int16
#undef int32
#define uint8 unsigned char #define uint8 unsigned char
#define uint16 unsigned short #define uint16 unsigned short
@ -8,3 +11,8 @@
#define int8 signed char #define int8 signed char
#define int16 signed short #define int16 signed short
#define int32 signed int #define int32 signed int
/* C89 compatibility */
#ifndef M_PI
#define M_PI 3.14159265358979323846264338327
#endif

View File

@ -42,7 +42,7 @@
#include "shared.h" #include "shared.h"
#include "hvc.h" #include "hvc.h"
/* Mark a pattern as dirty */ /* Mark a pattern as modified */
#define MARK_BG_DIRTY(addr) \ #define MARK_BG_DIRTY(addr) \
{ \ { \
name = (addr >> 5) & 0x7FF; \ name = (addr >> 5) & 0x7FF; \
@ -73,7 +73,6 @@ uint16 hscb; /* Horizontal scroll table base address */
uint8 bg_name_dirty[0x800]; /* 1= This pattern is dirty */ uint8 bg_name_dirty[0x800]; /* 1= This pattern is dirty */
uint16 bg_name_list[0x800]; /* List of modified pattern indices */ uint16 bg_name_list[0x800]; /* List of modified pattern indices */
uint16 bg_list_index; /* # of modified patterns in list */ uint16 bg_list_index; /* # of modified patterns in list */
uint8 bg_pattern_cache[0x80000]; /* Cached and flipped patterns */
uint8 hscroll_mask; /* Horizontal Scrolling line mask */ uint8 hscroll_mask; /* Horizontal Scrolling line mask */
uint8 playfield_shift; /* Width of planes A, B (in bits) */ uint8 playfield_shift; /* Width of planes A, B (in bits) */
uint8 playfield_col_mask; /* Playfield column mask */ uint8 playfield_col_mask; /* Playfield column mask */
@ -139,7 +138,6 @@ static const uint16 vc_table[4][2] =
{0x106, 0x10A} /* Mode 5 (240 lines) */ {0x106, 0x10A} /* Mode 5 (240 lines) */
}; };
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
/* Function prototypes */ /* Function prototypes */
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
@ -162,7 +160,6 @@ static void vdp_dma_copy(int length);
static void vdp_dma_vbus(int length); static void vdp_dma_vbus(int length);
static void vdp_dma_fill(unsigned int data, int length); static void vdp_dma_fill(unsigned int data, int length);
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
/* Init, reset, context functions */ /* Init, reset, context functions */
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
@ -196,6 +193,8 @@ void vdp_init(void)
void vdp_reset(void) void vdp_reset(void)
{ {
int i;
memset ((char *) sat, 0, sizeof (sat)); memset ((char *) sat, 0, sizeof (sat));
memset ((char *) vram, 0, sizeof (vram)); memset ((char *) vram, 0, sizeof (vram));
memset ((char *) cram, 0, sizeof (cram)); memset ((char *) cram, 0, sizeof (cram));
@ -235,11 +234,10 @@ void vdp_reset(void)
sat_base_mask = 0xFE00; sat_base_mask = 0xFE00;
sat_addr_mask = 0x01FF; sat_addr_mask = 0x01FF;
/* clear pattern cache */ /* reset pattern cache changes */
bg_list_index = 0; bg_list_index = 0;
memset ((char *) bg_name_dirty, 0, sizeof (bg_name_dirty)); memset ((char *) bg_name_dirty, 0, sizeof (bg_name_dirty));
memset ((char *) bg_name_list, 0, sizeof (bg_name_list)); memset ((char *) bg_name_list, 0, sizeof (bg_name_list));
memset ((char *) bg_pattern_cache, 0, sizeof (bg_pattern_cache));
/* default HVC */ /* default HVC */
hvc_latch = 0x10000; hvc_latch = 0x10000;
@ -284,7 +282,7 @@ void vdp_reset(void)
/* default rendering mode */ /* default rendering mode */
update_bg_pattern_cache = update_bg_pattern_cache_m4; update_bg_pattern_cache = update_bg_pattern_cache_m4;
if (system_hw < SYSTEM_SMS) if (system_hw < SYSTEM_MD)
{ {
/* Mode 0 */ /* Mode 0 */
render_bg = render_bg_m0; render_bg = render_bg_m0;
@ -299,11 +297,11 @@ void vdp_reset(void)
parse_satb = parse_satb_m4; parse_satb = parse_satb_m4;
} }
/* default 68k bus access mode (Mode 4) */ /* 68k bus access mode (Mode 4 by default) */
vdp_68k_data_w = vdp_68k_data_w_m4; vdp_68k_data_w = vdp_68k_data_w_m4;
vdp_68k_data_r = vdp_68k_data_r_m4; vdp_68k_data_r = vdp_68k_data_r_m4;
/* default Z80 bus access mode */ /* Z80 bus access mode */
switch (system_hw) switch (system_hw)
{ {
case SYSTEM_SG: case SYSTEM_SG:
@ -344,12 +342,12 @@ void vdp_reset(void)
if (system_hw == SYSTEM_SG) if (system_hw == SYSTEM_SG)
{ {
/* disable H-INT */ /* no H-INT on TMS9918 */
vdp_reg_w(10, 0xFF, 0); vdp_reg_w(10, 0xFF, 0);
} }
else if ((system_hw > SYSTEM_MARKIII) && (system_hw < SYSTEM_MD)) else if ((system_hw & SYSTEM_SMS) && ((config.bios & (SYSTEM_SMS | 0x01)) != (SYSTEM_SMS | 0x01)))
{ {
/* initialize registers normally set by Master System BIOS */ /* force registers initialization (if not done by Master System BIOS) */
vdp_reg_w(0 , 0x36, 0); vdp_reg_w(0 , 0x36, 0);
vdp_reg_w(1 , 0x80, 0); vdp_reg_w(1 , 0x80, 0);
vdp_reg_w(2 , 0xFF, 0); vdp_reg_w(2 , 0xFF, 0);
@ -358,10 +356,15 @@ void vdp_reset(void)
vdp_reg_w(5 , 0xFF, 0); vdp_reg_w(5 , 0xFF, 0);
vdp_reg_w(6 , 0xFF, 0); vdp_reg_w(6 , 0xFF, 0);
vdp_reg_w(10, 0xFF, 0); vdp_reg_w(10, 0xFF, 0);
/* Mode 4 */
render_bg = render_bg_m4;
render_obj = render_obj_m4;
parse_satb = parse_satb_m4;
} }
else if ((system_hw != SYSTEM_PBC) && (config.tmss == 1)) else if ((system_hw == SYSTEM_MD) && ((config.bios & (SYSTEM_MD | 0x01)) == 0x01))
{ {
/* initialize registers if BIOS is simulated */ /* force registers initialization on TMSS model (if not done by BOOT ROM) */
vdp_reg_w(0 , 0x04, 0); vdp_reg_w(0 , 0x04, 0);
vdp_reg_w(1 , 0x04, 0); vdp_reg_w(1 , 0x04, 0);
vdp_reg_w(10, 0xFF, 0); vdp_reg_w(10, 0xFF, 0);
@ -370,7 +373,6 @@ void vdp_reset(void)
} }
/* reset color palette */ /* reset color palette */
int i;
for(i = 0; i < 0x20; i ++) for(i = 0; i < 0x20; i ++)
{ {
color_update_m4(i, 0x00); color_update_m4(i, 0x00);
@ -401,7 +403,7 @@ int vdp_context_save(uint8 *state)
return bufferptr; return bufferptr;
} }
int vdp_context_load(uint8 *state, char *version) int vdp_context_load(uint8 *state)
{ {
int i, bufferptr = 0; int i, bufferptr = 0;
uint8 temp_reg[0x20]; uint8 temp_reg[0x20];
@ -419,11 +421,6 @@ int vdp_context_load(uint8 *state, char *version)
load_param(&dmafill, sizeof(dmafill)); load_param(&dmafill, sizeof(dmafill));
load_param(&hint_pending, sizeof(hint_pending)); load_param(&hint_pending, sizeof(hint_pending));
load_param(&vint_pending, sizeof(vint_pending)); load_param(&vint_pending, sizeof(vint_pending));
if ((version[11] <= 0x31) && (version[13] <= 0x35))
{
uint8 dummy;
load_param(&dummy, sizeof(dummy));
}
load_param(&dma_length, sizeof(dma_length)); load_param(&dma_length, sizeof(dma_length));
load_param(&dma_type, sizeof(dma_type)); load_param(&dma_type, sizeof(dma_type));
load_param(&cached_write, sizeof(cached_write)); load_param(&cached_write, sizeof(cached_write));
@ -522,7 +519,7 @@ int vdp_context_load(uint8 *state, char *version)
void vdp_dma_update(unsigned int cycles) void vdp_dma_update(unsigned int cycles)
{ {
int dma_cycles; int dma_cycles, dma_bytes;
/* DMA transfer rate (bytes per line) /* DMA transfer rate (bytes per line)
@ -570,7 +567,7 @@ void vdp_dma_update(unsigned int cycles)
} }
/* Remaining DMA bytes for that line */ /* Remaining DMA bytes for that line */
int dma_bytes = (dma_cycles * rate) / MCYCLES_PER_LINE; dma_bytes = (dma_cycles * rate) / MCYCLES_PER_LINE;
#ifdef LOGVDP #ifdef LOGVDP
error("[%d(%d)][%d(%d)] DMA type %d (%d access/line)(%d cycles left)-> %d access (%d remaining) (%x)\n", v_counter, mcycles_68k/MCYCLES_PER_LINE, mcycles_68k, mcycles_68k%MCYCLES_PER_LINE,dma_type/4, rate, dma_cycles, dma_bytes, dma_length, m68k_get_reg(M68K_REG_PC)); error("[%d(%d)][%d(%d)] DMA type %d (%d access/line)(%d cycles left)-> %d access (%d remaining) (%x)\n", v_counter, mcycles_68k/MCYCLES_PER_LINE, mcycles_68k, mcycles_68k%MCYCLES_PER_LINE,dma_type/4, rate, dma_cycles, dma_bytes, dma_length, m68k_get_reg(M68K_REG_PC));
@ -856,7 +853,7 @@ void vdp_z80_ctrl_w(unsigned int data)
{ {
case 2: case 2:
{ {
/* VRAM write operation only (Williams Greatest Hits after soft reset) */ /* VRAM write operation only */
if ((code & 0x0F) == 1) if ((code & 0x0F) == 1)
{ {
/* VRAM fill will be triggered by next write to DATA port */ /* VRAM fill will be triggered by next write to DATA port */
@ -933,17 +930,14 @@ void vdp_sms_ctrl_w(unsigned int data)
if (code == 2) if (code == 2)
{ {
/* VDP register index (0-15) */
data &= 0x0F;
/* Save current VDP mode */ /* Save current VDP mode */
int prev = (reg[0] & 0x06) | (reg[1] & 0x18); int mode, prev = (reg[0] & 0x06) | (reg[1] & 0x18);
/* Write VDP register */ /* Write VDP register 0-15 */
vdp_reg_w(data, addr_latch, mcycles_z80); vdp_reg_w(data & 0x0F, addr_latch, mcycles_z80);
/* Check VDP mode changes */ /* Check VDP mode changes */
int mode = (reg[0] & 0x06) | (reg[1] & 0x18); mode = (reg[0] & 0x06) | (reg[1] & 0x18);
prev ^= mode; prev ^= mode;
if (prev) if (prev)
@ -1072,6 +1066,8 @@ void vdp_sms_ctrl_w(unsigned int data)
/* Mode switching */ /* Mode switching */
if (prev & 0x04) if (prev & 0x04)
{ {
int i;
if (mode & 0x04) if (mode & 0x04)
{ {
/* Mode 4 sprites */ /* Mode 4 sprites */
@ -1092,7 +1088,6 @@ void vdp_sms_ctrl_w(unsigned int data)
} }
/* reinitialize palette */ /* reinitialize palette */
int i;
for(i = 0; i < 0x20; i ++) for(i = 0; i < 0x20; i ++)
{ {
color_update_m4(i, *(uint16 *)&cram[i << 1]); color_update_m4(i, *(uint16 *)&cram[i << 1]);
@ -1221,6 +1216,7 @@ void vdp_tms_ctrl_w(unsigned int data)
*/ */
unsigned int vdp_68k_ctrl_r(unsigned int cycles) unsigned int vdp_68k_ctrl_r(unsigned int cycles)
{ {
unsigned int temp;
/* Update FIFO flags */ /* Update FIFO flags */
vdp_fifo_update(cycles); vdp_fifo_update(cycles);
@ -1232,7 +1228,7 @@ unsigned int vdp_68k_ctrl_r(unsigned int cycles)
} }
/* Return VDP status */ /* Return VDP status */
unsigned int temp = status; temp = status;
/* Clear pending flag */ /* Clear pending flag */
pending = 0; pending = 0;
@ -1261,15 +1257,17 @@ unsigned int vdp_68k_ctrl_r(unsigned int cycles)
unsigned int vdp_z80_ctrl_r(unsigned int cycles) unsigned int vdp_z80_ctrl_r(unsigned int cycles)
{ {
unsigned int temp;
/* Cycle-accurate SOVR & VINT flags */
int line = (lines_per_frame + (cycles / MCYCLES_PER_LINE) - 1) % lines_per_frame;
/* Update DMA Busy flag (Mega Drive VDP specific) */ /* Update DMA Busy flag (Mega Drive VDP specific) */
if ((system_hw & SYSTEM_MD) && (status & 2) && !dma_length && (cycles >= dma_endCycles)) if ((system_hw & SYSTEM_MD) && (status & 2) && !dma_length && (cycles >= dma_endCycles))
{ {
status &= 0xFD; status &= 0xFD;
} }
/* Cycle-accurate SOVR & VINT flags */
int line = (lines_per_frame + (mcycles_z80 / MCYCLES_PER_LINE) - 1) % lines_per_frame;
/* Check if we are already on next line */ /* Check if we are already on next line */
if (line > v_counter) if (line > v_counter)
{ {
@ -1287,7 +1285,7 @@ unsigned int vdp_z80_ctrl_r(unsigned int cycles)
} }
/* Return VDP status */ /* Return VDP status */
unsigned int temp = status; temp = status;
/* Clear pending flag */ /* Clear pending flag */
pending = 0; pending = 0;
@ -1358,16 +1356,42 @@ unsigned int vdp_z80_ctrl_r(unsigned int cycles)
unsigned int vdp_hvc_r(unsigned int cycles) unsigned int vdp_hvc_r(unsigned int cycles)
{ {
/* VCounter */ int vc;
int vc = (cycles / MCYCLES_PER_LINE) - 1; unsigned int temp = hvc_latch;
/* Check counter overflow */ /* Check if HVC is frozen */
if (!temp)
{
/* Cycle-accurate HCounter (Striker, Mickey Mania, Skitchin, Road Rash I,II,III, Sonic 3D Blast...) */
temp = hctab[cycles % MCYCLES_PER_LINE];
}
else
{
if (reg[1] & 4)
{
/* Mode 5: both counters are frozen (Lightgun games, Sunset Riders) */
#ifdef LOGVDP
error("[%d(%d)][%d(%d)] HVC read -> 0x%x (%x)\n", v_counter, (cycles/MCYCLES_PER_LINE-1)%lines_per_frame, cycles, cycles%MCYCLES_PER_LINE, hvc_latch & 0xffff, m68k_get_reg(M68K_REG_PC));
#endif
return (temp & 0xffff);
}
else
{
/* Mode 4: VCounter runs normally, HCounter is frozen */
temp &= 0xff;
}
}
/* Cycle-accurate VCounter (cycle counter starts from line -1) */
vc = (cycles / MCYCLES_PER_LINE) - 1;
/* VCounter overflow */
if (vc > vc_max) if (vc > vc_max)
{ {
vc -= lines_per_frame; vc -= lines_per_frame;
} }
/* Check interlaced modes */ /* Interlaced modes */
if (interlaced) if (interlaced)
{ {
/* Interlace mode 2 (Sonic the Hedgehog 2, Combat Cars) */ /* Interlace mode 2 (Sonic the Hedgehog 2, Combat Cars) */
@ -1377,28 +1401,7 @@ unsigned int vdp_hvc_r(unsigned int cycles)
vc = (vc & ~1) | ((vc >> 8) & 1); vc = (vc & ~1) | ((vc >> 8) & 1);
} }
/* Returned value */ temp |= ((vc & 0xff) << 8);
unsigned int temp = (vc & 0xff) << 8;
/* Check if HVC is frozen */
if (!hvc_latch)
{
/* Cycle-accurate HCounter (Striker, Mickey Mania, Skitchin, Road Rash I,II,III, Sonic 3D Blast...) */
temp |= hctab[cycles % MCYCLES_PER_LINE];
}
else
{
if (reg[1] & 4)
{
/* Mode 5: both counters are frozen (Lightgun games, Sunset Riders) */
temp = hvc_latch & 0xffff;
}
else
{
/* Mode 4: VCounter runs normally, HCounter is frozen */
temp |= (hvc_latch & 0xff);
}
}
#ifdef LOGVDP #ifdef LOGVDP
error("[%d(%d)][%d(%d)] HVC read -> 0x%x (%x)\n", v_counter, (cycles/MCYCLES_PER_LINE-1)%lines_per_frame, cycles, cycles%MCYCLES_PER_LINE, temp, m68k_get_reg(M68K_REG_PC)); error("[%d(%d)][%d(%d)] HVC read -> 0x%x (%x)\n", v_counter, (cycles/MCYCLES_PER_LINE-1)%lines_per_frame, cycles, cycles%MCYCLES_PER_LINE, temp, m68k_get_reg(M68K_REG_PC));
@ -1881,6 +1884,8 @@ static void vdp_reg_w(unsigned int r, unsigned int d, unsigned int cycles)
case 8: /* Horizontal Scroll (Mode 4 only) */ case 8: /* Horizontal Scroll (Mode 4 only) */
{ {
int line;
/* Hscroll is latched at HCount 0xF3, HCount 0xF6 on MD */ /* Hscroll is latched at HCount 0xF3, HCount 0xF6 on MD */
/* Line starts at HCount 0xF4, HCount 0xF6 on MD */ /* Line starts at HCount 0xF4, HCount 0xF6 on MD */
if (system_hw < SYSTEM_MD) if (system_hw < SYSTEM_MD)
@ -1889,7 +1894,7 @@ static void vdp_reg_w(unsigned int r, unsigned int d, unsigned int cycles)
} }
/* Make sure Hscroll has not already been latched */ /* Make sure Hscroll has not already been latched */
int line = (lines_per_frame + (cycles / MCYCLES_PER_LINE) - 1) % lines_per_frame; line = (lines_per_frame + (cycles / MCYCLES_PER_LINE) - 1) % lines_per_frame;
if ((line > v_counter) && (line < bitmap.viewport.h) && !(work_ram[0x1ffb] & cart.special)) if ((line > v_counter) && (line < bitmap.viewport.h) && !(work_ram[0x1ffb] & cart.special))
{ {
v_counter = line; v_counter = line;
@ -2092,21 +2097,18 @@ static void vdp_bus_w(unsigned int data)
{ {
case 0x01: /* VRAM */ case 0x01: /* VRAM */
{ {
#ifdef LOGVDP
error("[%d(%d)][%d(%d)] VRAM 0x%x write -> 0x%x (%x)\n", v_counter, mcycles_68k/MCYCLES_PER_LINE-1, mcycles_68k, mcycles_68k%MCYCLES_PER_LINE, addr, data, m68k_get_reg(M68K_REG_PC));
#endif
/* Byte-swap data if A0 is set */
if (addr & 1)
{
data = ((data >> 8) | (data << 8)) & 0xFFFF;
}
/* VRAM address */ /* VRAM address */
int index = addr & 0xFFFE; int index = addr & 0xFFFE;
/* Pointer to VRAM */ /* Pointer to VRAM */
uint16 *p = (uint16 *)&vram[index]; uint16 *p = (uint16 *)&vram[index];
/* Byte-swap data if A0 is set */
if (addr & 1)
{
data = ((data >> 8) | (data << 8)) & 0xFFFF;
}
/* Intercept writes to Sprite Attribute Table */ /* Intercept writes to Sprite Attribute Table */
if ((index & sat_base_mask) == satb) if ((index & sat_base_mask) == satb)
{ {
@ -2117,21 +2119,23 @@ static void vdp_bus_w(unsigned int data)
/* Only write unique data to VRAM */ /* Only write unique data to VRAM */
if (data != *p) if (data != *p)
{ {
int name;
/* Write data to VRAM */ /* Write data to VRAM */
*p = data; *p = data;
/* Update pattern cache */ /* Update pattern cache */
int name;
MARK_BG_DIRTY (index); MARK_BG_DIRTY (index);
} }
#ifdef LOGVDP
error("[%d(%d)][%d(%d)] VRAM 0x%x write -> 0x%x (%x)\n", v_counter, mcycles_68k/MCYCLES_PER_LINE-1, mcycles_68k, mcycles_68k%MCYCLES_PER_LINE, addr, data, m68k_get_reg(M68K_REG_PC));
#endif
break; break;
} }
case 0x03: /* CRAM */ case 0x03: /* CRAM */
{ {
#ifdef LOGVDP
error("[%d(%d)][%d(%d)] CRAM 0x%x write -> 0x%x (%x)\n", v_counter, mcycles_68k/MCYCLES_PER_LINE-1, mcycles_68k, mcycles_68k%MCYCLES_PER_LINE, addr, data, m68k_get_reg(M68K_REG_PC));
#endif
/* Pointer to CRAM 9-bit word */ /* Pointer to CRAM 9-bit word */
uint16 *p = (uint16 *)&cram[addr & 0x7E]; uint16 *p = (uint16 *)&cram[addr & 0x7E];
@ -2141,12 +2145,12 @@ static void vdp_bus_w(unsigned int data)
/* Check if CRAM data is being modified */ /* Check if CRAM data is being modified */
if (data != *p) if (data != *p)
{ {
/* Write CRAM data */
*p = data;
/* CRAM index (64 words) */ /* CRAM index (64 words) */
int index = (addr >> 1) & 0x3F; int index = (addr >> 1) & 0x3F;
/* Write CRAM data */
*p = data;
/* Color entry 0 of each palette is never displayed (transparent pixel) */ /* Color entry 0 of each palette is never displayed (transparent pixel) */
if (index & 0x0F) if (index & 0x0F)
{ {
@ -2167,14 +2171,14 @@ static void vdp_bus_w(unsigned int data)
remap_line(v_counter); remap_line(v_counter);
} }
} }
#ifdef LOGVDP
error("[%d(%d)][%d(%d)] CRAM 0x%x write -> 0x%x (%x)\n", v_counter, mcycles_68k/MCYCLES_PER_LINE-1, mcycles_68k, mcycles_68k%MCYCLES_PER_LINE, addr, data, m68k_get_reg(M68K_REG_PC));
#endif
break; break;
} }
case 0x05: /* VSRAM */ case 0x05: /* VSRAM */
{ {
#ifdef LOGVDP
error("[%d(%d)][%d(%d)] VSRAM 0x%x write -> 0x%x (%x)\n", v_counter, mcycles_68k/MCYCLES_PER_LINE-1, mcycles_68k, mcycles_68k%MCYCLES_PER_LINE, addr, data, m68k_get_reg(M68K_REG_PC));
#endif
*(uint16 *)&vsram[addr & 0x7E] = data; *(uint16 *)&vsram[addr & 0x7E] = data;
/* 2-cell Vscroll mode */ /* 2-cell Vscroll mode */
@ -2187,16 +2191,19 @@ static void vdp_bus_w(unsigned int data)
render_line(v_counter); render_line(v_counter);
} }
} }
#ifdef LOGVDP
error("[%d(%d)][%d(%d)] VSRAM 0x%x write -> 0x%x (%x)\n", v_counter, mcycles_68k/MCYCLES_PER_LINE-1, mcycles_68k, mcycles_68k%MCYCLES_PER_LINE, addr, data, m68k_get_reg(M68K_REG_PC));
#endif
break; break;
} }
#ifdef LOGERROR
default: default:
{ {
#ifdef LOGERROR
error("[%d(%d)][%d(%d)] Unknown (%d) 0x%x write -> 0x%x (%x)\n", v_counter, mcycles_68k/MCYCLES_PER_LINE-1, mcycles_68k, mcycles_68k%MCYCLES_PER_LINE, code, addr, data, m68k_get_reg(M68K_REG_PC)); error("[%d(%d)][%d(%d)] Unknown (%d) 0x%x write -> 0x%x (%x)\n", v_counter, mcycles_68k/MCYCLES_PER_LINE-1, mcycles_68k, mcycles_68k%MCYCLES_PER_LINE, code, addr, data, m68k_get_reg(M68K_REG_PC));
#endif
break; break;
} }
#endif
} }
/* Increment address register (TODO: see how address is incremented in Mode 4) */ /* Increment address register (TODO: see how address is incremented in Mode 4) */
@ -2269,26 +2276,27 @@ static void vdp_68k_data_w_m4(unsigned int data)
} }
else else
{ {
/* Byte-swap data if A0 is set */
if (addr & 1)
{
data = ((data >> 8) | (data << 8)) & 0xFFFF;
}
/* VRAM address (interleaved format) */ /* VRAM address (interleaved format) */
int index = ((addr << 1) & 0x3FC) | ((addr & 0x200) >> 8) | (addr & 0x3C00); int index = ((addr << 1) & 0x3FC) | ((addr & 0x200) >> 8) | (addr & 0x3C00);
/* Pointer to VRAM */ /* Pointer to VRAM */
uint16 *p = (uint16 *)&vram[index]; uint16 *p = (uint16 *)&vram[index];
/* Byte-swap data if A0 is set */
if (addr & 1)
{
data = ((data >> 8) | (data << 8)) & 0xFFFF;
}
/* Only write unique data to VRAM */ /* Only write unique data to VRAM */
if (data != *p) if (data != *p)
{ {
int name;
/* Write data to VRAM */ /* Write data to VRAM */
*p = data; *p = data;
/* Update the pattern cache */ /* Update the pattern cache */
int name;
MARK_BG_DIRTY (index); MARK_BG_DIRTY (index);
} }
} }
@ -2354,12 +2362,12 @@ static void vdp_68k_data_w_m5(unsigned int data)
static unsigned int vdp_68k_data_r_m4(void) static unsigned int vdp_68k_data_r_m4(void)
{ {
/* Clear pending flag */
pending = 0;
/* VRAM address (interleaved format) */ /* VRAM address (interleaved format) */
int index = ((addr << 1) & 0x3FC) | ((addr & 0x200) >> 8) | (addr & 0x3C00); int index = ((addr << 1) & 0x3FC) | ((addr & 0x200) >> 8) | (addr & 0x3C00);
/* Clear pending flag */
pending = 0;
/* Increment address register */ /* Increment address register */
addr += (reg[15] + 1); addr += (reg[15] + 1);
@ -2472,11 +2480,12 @@ static void vdp_z80_data_w_m4(unsigned int data)
/* Only write unique data to VRAM */ /* Only write unique data to VRAM */
if (data != vram[index]) if (data != vram[index])
{ {
int name;
/* Write data */ /* Write data */
vram[index] = data; vram[index] = data;
/* Update pattern cache */ /* Update pattern cache */
int name;
MARK_BG_DIRTY(index); MARK_BG_DIRTY(index);
} }
} }
@ -2508,11 +2517,12 @@ static void vdp_z80_data_w_m5(unsigned int data)
/* Only write unique data to VRAM */ /* Only write unique data to VRAM */
if (data != READ_BYTE(vram, index)) if (data != READ_BYTE(vram, index))
{ {
int name;
/* Write data */ /* Write data */
WRITE_BYTE(vram, index, data); WRITE_BYTE(vram, index, data);
/* Update pattern cache */ /* Update pattern cache */
int name;
MARK_BG_DIRTY (index); MARK_BG_DIRTY (index);
} }
break; break;
@ -2538,12 +2548,12 @@ static void vdp_z80_data_w_m5(unsigned int data)
/* Check if CRAM data is being modified */ /* Check if CRAM data is being modified */
if (data != *p) if (data != *p)
{ {
/* Write CRAM data */
*p = data;
/* CRAM index (64 words) */ /* CRAM index (64 words) */
int index = (addr >> 1) & 0x3F; int index = (addr >> 1) & 0x3F;
/* Write CRAM data */
*p = data;
/* Color entry 0 of each palette is never displayed (transparent pixel) */ /* Color entry 0 of each palette is never displayed (transparent pixel) */
if (index & 0x0F) if (index & 0x0F)
{ {
@ -2594,12 +2604,12 @@ static void vdp_z80_data_w_m5(unsigned int data)
static unsigned int vdp_z80_data_r_m4(void) static unsigned int vdp_z80_data_r_m4(void)
{ {
/* Clear pending flag */
pending = 0;
/* Read buffer */ /* Read buffer */
unsigned int data = fifo[0]; unsigned int data = fifo[0];
/* Clear pending flag */
pending = 0;
/* Process next read */ /* Process next read */
fifo[0] = vram[addr & 0x3FFF]; fifo[0] = vram[addr & 0x3FFF];
@ -2671,6 +2681,8 @@ static void vdp_z80_data_w_ms(unsigned int data)
if (code < 3) if (code < 3)
{ {
int index;
/* check if we are already on next line */ /* check if we are already on next line */
int line = (lines_per_frame + (mcycles_z80 / MCYCLES_PER_LINE) - 1) % lines_per_frame; int line = (lines_per_frame + (mcycles_z80 / MCYCLES_PER_LINE) - 1) % lines_per_frame;
if ((line > v_counter) && (line < bitmap.viewport.h) && !(work_ram[0x1ffb] & cart.special)) if ((line > v_counter) && (line < bitmap.viewport.h) && !(work_ram[0x1ffb] & cart.special))
@ -2680,25 +2692,26 @@ static void vdp_z80_data_w_ms(unsigned int data)
} }
/* VRAM address */ /* VRAM address */
int index = addr & 0x3FFF; index = addr & 0x3FFF;
#ifdef LOGVDP #ifdef LOGVDP
error("[%d(%d)][%d(%d)] VRAM 0x%x write -> 0x%x (%x)\n", v_counter, mcycles_z80/MCYCLES_PER_LINE-1, mcycles_z80, mcycles_z80%MCYCLES_PER_LINE, index, data, Z80.pc.w.l); error("[%d(%d)][%d(%d)] VRAM 0x%x write -> 0x%x (%x)\n", v_counter, mcycles_z80/MCYCLES_PER_LINE-1, mcycles_z80, mcycles_z80%MCYCLES_PER_LINE, index, data, Z80.pc.w.l);
#endif #endif
/* VRAM write */ /* VRAM write */
if(data != vram[index]) if (data != vram[index])
{ {
int name; int name;
vram[index] = data; vram[index] = data;
MARK_BG_DIRTY(index); MARK_BG_DIRTY(index);
} }
#ifdef LOGVDP
error("[%d(%d)][%d(%d)] VRAM 0x%x write -> 0x%x (%x)\n", v_counter, mcycles_z80/MCYCLES_PER_LINE-1, mcycles_z80, mcycles_z80%MCYCLES_PER_LINE, index, data, Z80.pc.w.l);
#endif
} }
else else
{ {
#ifdef LOGVDP
error("[%d(%d)][%d(%d)] CRAM 0x%x write -> 0x%x (%x)\n", v_counter, mcycles_z80/MCYCLES_PER_LINE-1, mcycles_z80, mcycles_z80%MCYCLES_PER_LINE, addr, data, Z80.pc.w.l);
#endif
/* CRAM address */ /* CRAM address */
int index = addr & 0x1F; int index = addr & 0x1F;
@ -2720,6 +2733,9 @@ static void vdp_z80_data_w_ms(unsigned int data)
color_update_m4(0x40, data); color_update_m4(0x40, data);
} }
} }
#ifdef LOGVDP
error("[%d(%d)][%d(%d)] CRAM 0x%x write -> 0x%x (%x)\n", v_counter, mcycles_z80/MCYCLES_PER_LINE-1, mcycles_z80, mcycles_z80%MCYCLES_PER_LINE, addr, data, Z80.pc.w.l);
#endif
} }
/* Update read buffer */ /* Update read buffer */
@ -2736,6 +2752,8 @@ static void vdp_z80_data_w_gg(unsigned int data)
if (code < 3) if (code < 3)
{ {
int index;
/* check if we are already on next line*/ /* check if we are already on next line*/
int line = (lines_per_frame + (mcycles_z80 / MCYCLES_PER_LINE) - 1) % lines_per_frame; int line = (lines_per_frame + (mcycles_z80 / MCYCLES_PER_LINE) - 1) % lines_per_frame;
if ((line > v_counter) && (line < bitmap.viewport.h) && !(work_ram[0x1ffb] & cart.special)) if ((line > v_counter) && (line < bitmap.viewport.h) && !(work_ram[0x1ffb] & cart.special))
@ -2745,39 +2763,42 @@ static void vdp_z80_data_w_gg(unsigned int data)
} }
/* VRAM address */ /* VRAM address */
int index = addr & 0x3FFF; index = addr & 0x3FFF;
#ifdef LOGVDP #ifdef LOGVDP
error("[%d(%d)][%d(%d)] VRAM 0x%x write -> 0x%x (%x)\n", v_counter, mcycles_z80/MCYCLES_PER_LINE-1, mcycles_z80, mcycles_z80%MCYCLES_PER_LINE, index, data, Z80.pc.w.l); error("[%d(%d)][%d(%d)] VRAM 0x%x write -> 0x%x (%x)\n", v_counter, mcycles_z80/MCYCLES_PER_LINE-1, mcycles_z80, mcycles_z80%MCYCLES_PER_LINE, index, data, Z80.pc.w.l);
#endif #endif
/* VRAM write */ /* VRAM write */
if(data != vram[index]) if (data != vram[index])
{ {
int name; int name;
vram[index] = data; vram[index] = data;
MARK_BG_DIRTY(index); MARK_BG_DIRTY(index);
} }
#ifdef LOGVDP
error("[%d(%d)][%d(%d)] VRAM 0x%x write -> 0x%x (%x)\n", v_counter, mcycles_z80/MCYCLES_PER_LINE-1, mcycles_z80, mcycles_z80%MCYCLES_PER_LINE, index, data, Z80.pc.w.l);
#endif
} }
else else
{ {
if(addr & 1) if (addr & 1)
{ {
/* 12-bit data word */
data = (data << 8) | cached_write;
/* Pointer to CRAM word */ /* Pointer to CRAM word */
uint16 *p = (uint16 *)&cram[addr & 0x3E]; uint16 *p = (uint16 *)&cram[addr & 0x3E];
/* 12-bit data word */
data = (data << 8) | cached_write;
/* Check if CRAM data is being modified */ /* Check if CRAM data is being modified */
if (data != *p) if (data != *p)
{ {
/* Write CRAM data */
*p = data;
/* Color index (0-31) */ /* Color index (0-31) */
int index = (addr >> 1) & 0x1F; int index = (addr >> 1) & 0x1F;
/* Write CRAM data */
*p = data;
/* Update color palette */ /* Update color palette */
color_update_m4(index, data); color_update_m4(index, data);
@ -2793,6 +2814,9 @@ static void vdp_z80_data_w_gg(unsigned int data)
/* Latch LSB */ /* Latch LSB */
cached_write = data; cached_write = data;
} }
#ifdef LOGVDP
error("[%d(%d)][%d(%d)] CRAM 0x%x write -> 0x%x (%x)\n", v_counter, mcycles_z80/MCYCLES_PER_LINE-1, mcycles_z80, mcycles_z80%MCYCLES_PER_LINE, addr, data, Z80.pc.w.l);
#endif
} }
/* Update read buffer */ /* Update read buffer */
@ -2804,12 +2828,12 @@ static void vdp_z80_data_w_gg(unsigned int data)
static void vdp_z80_data_w_sg(unsigned int data) static void vdp_z80_data_w_sg(unsigned int data)
{ {
/* Clear pending flag */
pending = 0;
/* VRAM address */ /* VRAM address */
int index = addr & 0x3FFF; int index = addr & 0x3FFF;
/* Clear pending flag */
pending = 0;
/* 4K address decoding (cf. tms9918a.txt) */ /* 4K address decoding (cf. tms9918a.txt) */
if (!(reg[1] & 0x80)) if (!(reg[1] & 0x80))
{ {
@ -2821,6 +2845,10 @@ static void vdp_z80_data_w_sg(unsigned int data)
/* Update address register */ /* Update address register */
addr++; addr++;
#ifdef LOGVDP
error("[%d(%d)][%d(%d)] VRAM 0x%x write -> 0x%x (%x)\n", v_counter, mcycles_z80/MCYCLES_PER_LINE-1, mcycles_z80, mcycles_z80%MCYCLES_PER_LINE, index, data, Z80.pc.w.l);
#endif
} }
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/

View File

@ -62,7 +62,6 @@ extern uint16 hscb;
extern uint8 bg_name_dirty[0x800]; extern uint8 bg_name_dirty[0x800];
extern uint16 bg_name_list[0x800]; extern uint16 bg_name_list[0x800];
extern uint16 bg_list_index; extern uint16 bg_list_index;
extern uint8 bg_pattern_cache[0x80000];
extern uint8 hscroll_mask; extern uint8 hscroll_mask;
extern uint8 playfield_shift; extern uint8 playfield_shift;
extern uint8 playfield_col_mask; extern uint8 playfield_col_mask;
@ -90,7 +89,7 @@ extern unsigned int (*vdp_z80_data_r)(void);
extern void vdp_init(void); extern void vdp_init(void);
extern void vdp_reset(void); extern void vdp_reset(void);
extern int vdp_context_save(uint8 *state); extern int vdp_context_save(uint8 *state);
extern int vdp_context_load(uint8 *state, char *version); extern int vdp_context_load(uint8 *state);
extern void vdp_dma_update(unsigned int cycles); extern void vdp_dma_update(unsigned int cycles);
extern void vdp_68k_ctrl_w(unsigned int data); extern void vdp_68k_ctrl_w(unsigned int data);
extern void vdp_z80_ctrl_w(unsigned int data); extern void vdp_z80_ctrl_w(unsigned int data);

View File

@ -539,6 +539,9 @@ static const uint32 tms_palette[16] =
}; };
#endif #endif
/* Cached and flipped patterns */
static uint8 bg_pattern_cache[0x80000];
/* Sprite pattern name offset look-up table (Mode 5) */ /* Sprite pattern name offset look-up table (Mode 5) */
static uint8 name_lut[0x400]; static uint8 name_lut[0x400];
@ -738,13 +741,15 @@ static uint32 make_lut_bg_ste(uint32 bx, uint32 ax)
/* Output: d5-d0=color, d6=priority, d7=sprite pixel marker */ /* Output: d5-d0=color, d6=priority, d7=sprite pixel marker */
static uint32 make_lut_obj(uint32 bx, uint32 sx) static uint32 make_lut_obj(uint32 bx, uint32 sx)
{ {
int c;
int bf = (bx & 0x7F); int bf = (bx & 0x7F);
int bs = (bx & 0x80); int bs = (bx & 0x80);
int sf = (sx & 0x7F); int sf = (sx & 0x7F);
if((sx & 0x0F) == 0) return bx; if((sx & 0x0F) == 0) return bx;
int c = (bs ? bf : sf); c = (bs ? bf : sf);
/* Strip palette bits from transparent pixels */ /* Strip palette bits from transparent pixels */
if((c & 0x0F) == 0x00) c &= 0xC0; if((c & 0x0F) == 0x00) c &= 0xC0;
@ -758,6 +763,8 @@ static uint32 make_lut_obj(uint32 bx, uint32 sx)
/* Output: d5-d0=color, d6=zero/priority, d7=opaque sprite pixel marker */ /* Output: d5-d0=color, d6=zero/priority, d7=opaque sprite pixel marker */
static uint32 make_lut_bgobj(uint32 bx, uint32 sx) static uint32 make_lut_bgobj(uint32 bx, uint32 sx)
{ {
int c;
int bf = (bx & 0x3F); int bf = (bx & 0x3F);
int bs = (bx & 0x80); int bs = (bx & 0x80);
int bp = (bx & 0x40); int bp = (bx & 0x40);
@ -772,7 +779,7 @@ static uint32 make_lut_bgobj(uint32 bx, uint32 sx)
/* Previous sprite has higher priority */ /* Previous sprite has higher priority */
if(bs) return bx; if(bs) return bx;
int c = (sp ? sf : (bp ? (b ? bf : sf) : sf)); c = (sp ? sf : (bp ? (b ? bf : sf) : sf));
/* Strip palette & priority bits from transparent pixels */ /* Strip palette & priority bits from transparent pixels */
if((c & 0x0F) == 0x00) c &= 0x80; if((c & 0x0F) == 0x00) c &= 0x80;
@ -914,6 +921,8 @@ static uint32 make_lut_bgobj_ste(uint32 bx, uint32 sx)
/* Output: d3-d0=color, d4=palette, d5=zero/priority, d6=zero, d7=sprite pixel marker */ /* Output: d3-d0=color, d4=palette, d5=zero/priority, d6=zero, d7=sprite pixel marker */
static uint32 make_lut_bgobj_m4(uint32 bx, uint32 sx) static uint32 make_lut_bgobj_m4(uint32 bx, uint32 sx)
{ {
int c;
int bf = (bx & 0x3F); int bf = (bx & 0x3F);
int bs = (bx & 0x80); int bs = (bx & 0x80);
int bp = (bx & 0x20); int bp = (bx & 0x20);
@ -929,7 +938,7 @@ static uint32 make_lut_bgobj_m4(uint32 bx, uint32 sx)
if(bs) return bx; if(bs) return bx;
/* note: priority bit is always 0 for Modes 0,1,2,3 */ /* note: priority bit is always 0 for Modes 0,1,2,3 */
int c = (bp ? (b ? bf : sf) : sf); c = (bp ? (b ? bf : sf) : sf);
return (c | 0x80); return (c | 0x80);
} }
@ -939,7 +948,7 @@ static uint32 make_lut_bgobj_m4(uint32 bx, uint32 sx)
/* Pixel layer merging function */ /* Pixel layer merging function */
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
static inline void merge(uint8 *srca, uint8 *srcb, uint8 *dst, uint8 *table, int width) static __inline__ void merge(uint8 *srca, uint8 *srcb, uint8 *dst, uint8 *table, int width)
{ {
do do
{ {
@ -1207,8 +1216,13 @@ void render_bg_m1(int line, int width)
void render_bg_m1x(int line, int width) void render_bg_m1x(int line, int width)
{ {
uint8 pattern; uint8 pattern;
uint8 *pg;
uint8 color = reg[7]; uint8 color = reg[7];
uint8 *lb = &linebuf[0][0x20];
uint8 *nt = &vram[((reg[2] << 10) & 0x3C00) + ((line >> 3) * 40)];
uint16 pg_mask = ~0x3800 ^ (reg[4] << 11); uint16 pg_mask = ~0x3800 ^ (reg[4] << 11);
/* Unused bits used as a mask on TMS9918 & 315-5124 VDP only */ /* Unused bits used as a mask on TMS9918 & 315-5124 VDP only */
@ -1217,9 +1231,7 @@ void render_bg_m1x(int line, int width)
pg_mask |= 0x1800; pg_mask |= 0x1800;
} }
uint8 *lb = &linebuf[0][0x20]; pg = &vram[((0x2000 + ((line & 0xC0) << 5)) & pg_mask) + (line & 7)];
uint8 *nt = &vram[((reg[2] << 10) & 0x3C00) + ((line >> 3) * 40)];
uint8 *pg = &vram[((0x2000 + ((line & 0xC0) << 5)) & pg_mask) + (line & 7)];
/* Left border (8 pixels) */ /* Left border (8 pixels) */
memset (lb, 0x40, 8); memset (lb, 0x40, 8);
@ -1250,6 +1262,10 @@ void render_bg_m2(int line, int width)
{ {
uint8 color, pattern; uint8 color, pattern;
uint16 name; uint16 name;
uint8 *ct, *pg;
uint8 *lb = &linebuf[0][0x20];
uint8 *nt = &vram[((reg[2] << 10) & 0x3C00) + ((line & 0xF8) << 2)];
uint16 ct_mask = ~0x3FC0 ^ (reg[3] << 6); uint16 ct_mask = ~0x3FC0 ^ (reg[3] << 6);
uint16 pg_mask = ~0x3800 ^ (reg[4] << 11); uint16 pg_mask = ~0x3800 ^ (reg[4] << 11);
@ -1261,10 +1277,8 @@ void render_bg_m2(int line, int width)
pg_mask |= 0x1800; pg_mask |= 0x1800;
} }
uint8 *lb = &linebuf[0][0x20]; ct = &vram[((0x2000 + ((line & 0xC0) << 5)) & ct_mask) + (line & 7)];
uint8 *nt = &vram[((reg[2] << 10) & 0x3C00) + ((line & 0xF8) << 2)]; pg = &vram[((0x2000 + ((line & 0xC0) << 5)) & pg_mask) + (line & 7)];
uint8 *ct = &vram[((0x2000 + ((line & 0xC0) << 5)) & ct_mask) + (line & 7)];
uint8 *pg = &vram[((0x2000 + ((line & 0xC0) << 5)) & pg_mask) + (line & 7)];
/* 32 x 8 pixels */ /* 32 x 8 pixels */
width = 32; width = 32;
@ -1322,6 +1336,10 @@ void render_bg_m3x(int line, int width)
{ {
uint8 color; uint8 color;
uint16 name; uint16 name;
uint8 *pg;
uint8 *lb = &linebuf[0][0x20];
uint8 *nt = &vram[((reg[2] << 10) & 0x3C00) + ((line & 0xF8) << 2)];
uint16 pg_mask = ~0x3800 ^ (reg[4] << 11); uint16 pg_mask = ~0x3800 ^ (reg[4] << 11);
@ -1331,9 +1349,7 @@ void render_bg_m3x(int line, int width)
pg_mask |= 0x1800; pg_mask |= 0x1800;
} }
uint8 *lb = &linebuf[0][0x20]; pg = &vram[((0x2000 + ((line & 0xC0) << 5)) & pg_mask) + ((line >> 2) & 7)];
uint8 *nt = &vram[((reg[2] << 10) & 0x3C00) + ((line & 0xF8) << 2)];
uint8 *pg = &vram[((0x2000 + ((line & 0xC0) << 5)) & pg_mask) + ((line >> 2) & 7)];
/* 32 x 8 pixels */ /* 32 x 8 pixels */
width = 32; width = 32;
@ -1398,6 +1414,9 @@ void render_bg_m4(int line, int width)
/* Background line buffer */ /* Background line buffer */
uint32 *dst = (uint32 *)&linebuf[0][0x20 + shift]; uint32 *dst = (uint32 *)&linebuf[0][0x20 + shift];
/* Vertical scrolling */
int v_line = line + vscroll;
/* Pattern name table mask */ /* Pattern name table mask */
uint16 nt_mask = ~0x3C00 ^ (reg[2] << 10); uint16 nt_mask = ~0x3C00 ^ (reg[2] << 10);
@ -1407,9 +1426,6 @@ void render_bg_m4(int line, int width)
nt_mask |= 0x400; nt_mask |= 0x400;
} }
/* Vertical scrolling */
int v_line = line + vscroll;
/* Test for extended modes (Master System II & Game gear VDP only) */ /* Test for extended modes (Master System II & Game gear VDP only) */
if (bitmap.viewport.h > 192) if (bitmap.viewport.h > 192)
{ {
@ -1499,6 +1515,13 @@ void render_bg_m5(int line, int width)
/* Common data */ /* Common data */
uint32 xscroll = *(uint32 *)&vram[hscb + ((line & hscroll_mask) << 2)]; uint32 xscroll = *(uint32 *)&vram[hscb + ((line & hscroll_mask) << 2)];
uint32 yscroll = *(uint32 *)&vsram[0]; uint32 yscroll = *(uint32 *)&vsram[0];
uint32 pf_col_mask = playfield_col_mask;
uint32 pf_row_mask = playfield_row_mask;
uint32 pf_shift = playfield_shift;
/* Window & Plane A */
int a = (reg[18] & 0x1F) << 3;
int w = (reg[18] >> 7) & 1;
/* Plane B width */ /* Plane B width */
int start = 0; int start = 0;
@ -1507,16 +1530,16 @@ void render_bg_m5(int line, int width)
/* Plane B scroll */ /* Plane B scroll */
#ifdef LSB_FIRST #ifdef LSB_FIRST
uint32 shift = (xscroll >> 16) & 0x0F; uint32 shift = (xscroll >> 16) & 0x0F;
uint32 index = playfield_col_mask + 1 - ((xscroll >> 20) & playfield_col_mask); uint32 index = pf_col_mask + 1 - ((xscroll >> 20) & pf_col_mask);
uint32 v_line = (line + ((yscroll >> 16) & 0x3FF)) & playfield_row_mask; uint32 v_line = (line + ((yscroll >> 16) & 0x3FF)) & pf_row_mask;
#else #else
uint32 shift = (xscroll & 0x0F); uint32 shift = (xscroll & 0x0F);
uint32 index = playfield_col_mask + 1 - ((xscroll >> 4) & playfield_col_mask); uint32 index = pf_col_mask + 1 - ((xscroll >> 4) & pf_col_mask);
uint32 v_line = (line + (yscroll & 0x3FF)) & playfield_row_mask; uint32 v_line = (line + (yscroll & 0x3FF)) & pf_row_mask;
#endif #endif
/* Plane B name table */ /* Plane B name table */
uint32 *nt = (uint32 *)&vram[ntbb + (((v_line >> 3) << playfield_shift) & 0x1FC0)]; uint32 *nt = (uint32 *)&vram[ntbb + (((v_line >> 3) << pf_shift) & 0x1FC0)];
/* Pattern row index */ /* Pattern row index */
v_line = (v_line & 7) << 3; v_line = (v_line & 7) << 3;
@ -1526,7 +1549,7 @@ void render_bg_m5(int line, int width)
/* Plane B line buffer */ /* Plane B line buffer */
dst = (uint32 *)&linebuf[0][0x10 + shift]; dst = (uint32 *)&linebuf[0][0x10 + shift];
atbuf = nt[(index - 1) & playfield_col_mask]; atbuf = nt[(index - 1) & pf_col_mask];
DRAW_COLUMN(atbuf, v_line) DRAW_COLUMN(atbuf, v_line)
} }
else else
@ -1537,14 +1560,10 @@ void render_bg_m5(int line, int width)
for(column = 0; column < end; column++, index++) for(column = 0; column < end; column++, index++)
{ {
atbuf = nt[index & playfield_col_mask]; atbuf = nt[index & pf_col_mask];
DRAW_COLUMN(atbuf, v_line) DRAW_COLUMN(atbuf, v_line)
} }
/* Window & Plane A */
int a = (reg[18] & 0x1F) << 3;
int w = (reg[18] >> 7) & 1;
if (w == (line >= a)) if (w == (line >= a))
{ {
/* Window takes up entire line */ /* Window takes up entire line */
@ -1568,16 +1587,16 @@ void render_bg_m5(int line, int width)
/* Plane A scroll */ /* Plane A scroll */
#ifdef LSB_FIRST #ifdef LSB_FIRST
shift = (xscroll & 0x0F); shift = (xscroll & 0x0F);
index = playfield_col_mask + start + 1 - ((xscroll >> 4) & playfield_col_mask); index = pf_col_mask + start + 1 - ((xscroll >> 4) & pf_col_mask);
v_line = (line + (yscroll & 0x3FF)) & playfield_row_mask; v_line = (line + (yscroll & 0x3FF)) & pf_row_mask;
#else #else
shift = (xscroll >> 16) & 0x0F; shift = (xscroll >> 16) & 0x0F;
index = playfield_col_mask + start + 1 - ((xscroll >> 20) & playfield_col_mask); index = pf_col_mask + start + 1 - ((xscroll >> 20) & pf_col_mask);
v_line = (line + ((yscroll >> 16) & 0x3FF)) & playfield_row_mask; v_line = (line + ((yscroll >> 16) & 0x3FF)) & pf_row_mask;
#endif #endif
/* Plane A name table */ /* Plane A name table */
nt = (uint32 *)&vram[ntab + (((v_line >> 3) << playfield_shift) & 0x1FC0)]; nt = (uint32 *)&vram[ntab + (((v_line >> 3) << pf_shift) & 0x1FC0)];
/* Pattern row index */ /* Pattern row index */
v_line = (v_line & 7) << 3; v_line = (v_line & 7) << 3;
@ -1590,11 +1609,11 @@ void render_bg_m5(int line, int width)
/* Window bug */ /* Window bug */
if (start) if (start)
{ {
atbuf = nt[index & playfield_col_mask]; atbuf = nt[index & pf_col_mask];
} }
else else
{ {
atbuf = nt[(index - 1) & playfield_col_mask]; atbuf = nt[(index - 1) & pf_col_mask];
} }
DRAW_COLUMN(atbuf, v_line) DRAW_COLUMN(atbuf, v_line)
@ -1607,7 +1626,7 @@ void render_bg_m5(int line, int width)
for(column = start; column < end; column++, index++) for(column = start; column < end; column++, index++)
{ {
atbuf = nt[index & playfield_col_mask]; atbuf = nt[index & pf_col_mask];
DRAW_COLUMN(atbuf, v_line) DRAW_COLUMN(atbuf, v_line)
} }
@ -1650,6 +1669,10 @@ void render_bg_m5_vs(int line, int width)
uint32 pf_shift = playfield_shift; uint32 pf_shift = playfield_shift;
uint32 *vs = (uint32 *)&vsram[0]; uint32 *vs = (uint32 *)&vsram[0];
/* Window & Plane A */
int a = (reg[18] & 0x1F) << 3;
int w = (reg[18] >> 7) & 1;
/* Plane B width */ /* Plane B width */
int start = 0; int start = 0;
int end = width >> 4; int end = width >> 4;
@ -1663,9 +1686,10 @@ void render_bg_m5_vs(int line, int width)
uint32 index = pf_col_mask + 1 - ((xscroll >> 4) & pf_col_mask); uint32 index = pf_col_mask + 1 - ((xscroll >> 4) & pf_col_mask);
#endif #endif
/* Left-most column vertical scrolling when partially shown horizontally */ /* Left-most column vertical scrolling when partially shown horizontally (verified on PAL MD2) */
/* Same value for both planes, only in 40-cell mode, verified on PAL MD2 */ /* TODO: check on Genesis 3 models since it apparently behaves differently */
/* See Gynoug, Cutie Suzuki no Ringside Angel, Formula One, Kawasaki Superbike Challenge */ /* In H32 mode, vertical scrolling is disabled, in H40 mode, same value is used for both planes */
/* See Formula One / Kawasaki Superbike Challenge (H32) & Gynoug / Cutie Suzuki no Ringside Angel (H40) */
if (reg[12] & 1) if (reg[12] & 1)
{ {
yscroll = vs[19] & (vs[19] >> 16); yscroll = vs[19] & (vs[19] >> 16);
@ -1714,10 +1738,6 @@ void render_bg_m5_vs(int line, int width)
DRAW_COLUMN(atbuf, v_line) DRAW_COLUMN(atbuf, v_line)
} }
/* Window & Plane A */
int a = (reg[18] & 0x1F) << 3;
int w = (reg[18] >> 7) & 1;
if (w == (line >= a)) if (w == (line >= a))
{ {
/* Window takes up entire line */ /* Window takes up entire line */
@ -1829,13 +1849,16 @@ void render_bg_m5_im2(int line, int width)
uint32 atex, atbuf, *src, *dst; uint32 atex, atbuf, *src, *dst;
/* Common data */ /* Common data */
int odd = odd_frame;
uint32 xscroll = *(uint32 *)&vram[hscb + ((line & hscroll_mask) << 2)]; uint32 xscroll = *(uint32 *)&vram[hscb + ((line & hscroll_mask) << 2)];
uint32 yscroll = *(uint32 *)&vsram[0]; uint32 yscroll = *(uint32 *)&vsram[0];
uint32 pf_col_mask = playfield_col_mask; uint32 pf_col_mask = playfield_col_mask;
uint32 pf_row_mask = playfield_row_mask; uint32 pf_row_mask = playfield_row_mask;
uint32 pf_shift = playfield_shift; uint32 pf_shift = playfield_shift;
int odd = odd_frame; /* Window & Plane A */
int a = (reg[18] & 0x1F) << 3;
int w = (reg[18] >> 7) & 1;
/* Plane B width */ /* Plane B width */
int start = 0; int start = 0;
@ -1878,10 +1901,6 @@ void render_bg_m5_im2(int line, int width)
DRAW_COLUMN_IM2(atbuf, v_line) DRAW_COLUMN_IM2(atbuf, v_line)
} }
/* Window & Plane A */
int a = (reg[18] & 0x1F) << 3;
int w = (reg[18] >> 7) & 1;
if (w == (line >= a)) if (w == (line >= a))
{ {
/* Window takes up entire line */ /* Window takes up entire line */
@ -1980,6 +1999,7 @@ void render_bg_m5_im2_vs(int line, int width)
uint32 v_line, *nt; uint32 v_line, *nt;
/* Common data */ /* Common data */
int odd = odd_frame;
uint32 xscroll = *(uint32 *)&vram[hscb + ((line & hscroll_mask) << 2)]; uint32 xscroll = *(uint32 *)&vram[hscb + ((line & hscroll_mask) << 2)];
uint32 yscroll = 0; uint32 yscroll = 0;
uint32 pf_col_mask = playfield_col_mask; uint32 pf_col_mask = playfield_col_mask;
@ -1987,7 +2007,9 @@ void render_bg_m5_im2_vs(int line, int width)
uint32 pf_shift = playfield_shift; uint32 pf_shift = playfield_shift;
uint32 *vs = (uint32 *)&vsram[0]; uint32 *vs = (uint32 *)&vsram[0];
int odd = odd_frame; /* Window & Plane A */
int a = (reg[18] & 0x1F) << 3;
int w = (reg[18] >> 7) & 1;
/* Plane B width */ /* Plane B width */
int start = 0; int start = 0;
@ -2002,12 +2024,12 @@ void render_bg_m5_im2_vs(int line, int width)
uint32 index = pf_col_mask + 1 - ((xscroll >> 4) & pf_col_mask); uint32 index = pf_col_mask + 1 - ((xscroll >> 4) & pf_col_mask);
#endif #endif
/* Left-most column vertical scrolling when partially shown horizontally */ /* Left-most column vertical scrolling when partially shown horizontally (verified on PAL MD2) */
/* Same value for both planes, only in 40-cell mode, verified on PAL MD2 */ /* TODO: check on Genesis 3 models since it apparently behaves differently */
/* See Gynoug, Cutie Suzuki no Ringside Angel, Formula One, Kawasaki Superbike Challenge */ /* In H32 mode, vertical scrolling is disabled, in H40 mode, same value is used for both planes */
/* See Formula One / Kawasaki Superbike Challenge (H32) & Gynoug / Cutie Suzuki no Ringside Angel (H40) */
if (reg[12] & 1) if (reg[12] & 1)
{ {
/* only in 40-cell mode, verified on MD2 */
yscroll = (vs[19] >> 1) & (vs[19] >> 17); yscroll = (vs[19] >> 1) & (vs[19] >> 17);
yscroll &= 0x3FF; yscroll &= 0x3FF;
} }
@ -2054,10 +2076,6 @@ void render_bg_m5_im2_vs(int line, int width)
DRAW_COLUMN_IM2(atbuf, v_line) DRAW_COLUMN_IM2(atbuf, v_line)
} }
/* Window & Plane A */
int a = (reg[18] & 0x1F) << 3;
int w = (reg[18] >> 7) & 1;
if (w == (line >= a)) if (w == (line >= a))
{ {
/* Window takes up entire line */ /* Window takes up entire line */
@ -3008,15 +3026,15 @@ void render_obj_m4(int max_width)
/* Default sprite width */ /* Default sprite width */
int width = 8; int width = 8;
/* Sprite Generator address mask (LSB is masked for 8x16 sprites) */
uint16 sg_mask = (~0x1C0 ^ (reg[6] << 6)) & (~((reg[1] & 0x02) >> 1));
/* Zoomed sprites (not working on Genesis VDP) */ /* Zoomed sprites (not working on Genesis VDP) */
if (system_hw < SYSTEM_MD) if (system_hw < SYSTEM_MD)
{ {
width <<= (reg[1] & 0x01); width <<= (reg[1] & 0x01);
} }
/* Sprite Generator address mask (LSB is masked for 8x16 sprites) */
uint16 sg_mask = (~0x1C0 ^ (reg[6] << 6)) & (~((reg[1] & 0x02) >> 1));
/* Unused bits used as a mask on 315-5124 VDP only */ /* Unused bits used as a mask on 315-5124 VDP only */
if (system_hw > SYSTEM_SMS) if (system_hw > SYSTEM_SMS)
{ {
@ -3555,82 +3573,79 @@ void render_obj_m5_im2_ste(int max_width)
void parse_satb_tms(int line) void parse_satb_tms(int line)
{ {
if (reg[1] & 0x10)
{
/* no sprites in Text modes */
object_count = 0;
return;
}
int i = 0; int i = 0;
/* Pointer to sprite attribute table */
uint8 *st = &vram[(reg[5] << 7) & 0x3F80];
/* Sprite counter (4 max. per line) */ /* Sprite counter (4 max. per line) */
int count = 0; int count = 0;
/* Y position */ /* no sprites in Text modes */
int ypos; if (!(reg[1] & 0x10))
/* Sprite height (8 pixels by default) */
int height = 8;
/* Adjust height for 16x16 sprites */
height <<= ((reg[1] & 0x02) >> 1);
/* Adjust height for zoomed sprites */
height <<= (reg[1] & 0x01);
/* Parse Sprite Table (32 entries) */
do
{ {
/* Sprite Y position */ /* Pointer to sprite attribute table */
ypos = st[i << 2]; uint8 *st = &vram[(reg[5] << 7) & 0x3F80];
/* Check end of sprite list marker */ /* Y position */
if (ypos == 0xD0) int ypos;
/* Sprite height (8 pixels by default) */
int height = 8;
/* Adjust height for 16x16 sprites */
height <<= ((reg[1] & 0x02) >> 1);
/* Adjust height for zoomed sprites */
height <<= (reg[1] & 0x01);
/* Parse Sprite Table (32 entries) */
do
{ {
break; /* Sprite Y position */
} ypos = st[i << 2];
/* Wrap Y coordinate for sprites > 256-32 */ /* Check end of sprite list marker */
if (ypos >= 224) if (ypos == 0xD0)
{
ypos -= 256;
}
/* Y range */
ypos = line - ypos;
/* Sprite is visble on this line ? */
if ((ypos >= 0) && (ypos < height))
{
/* Sprite overflow */
if (count == 4)
{ {
/* Flag is set only during active area */
if (line < bitmap.viewport.h)
{
spr_ovr = 0x40;
}
break; break;
} }
/* Adjust Y range back for zoomed sprites */ /* Wrap Y coordinate for sprites > 256-32 */
ypos >>= (reg[1] & 0x01); if (ypos >= 224)
{
ypos -= 256;
}
/* Store sprite attributes for later processing */ /* Y range */
object_info[count].ypos = ypos; ypos = line - ypos;
object_info[count].xpos = st[(i << 2) + 1];
object_info[count].attr = st[(i << 2) + 2];
object_info[count].size = st[(i << 2) + 3];
/* Increment Sprite count */ /* Sprite is visble on this line ? */
++count; if ((ypos >= 0) && (ypos < height))
{
/* Sprite overflow */
if (count == 4)
{
/* Flag is set only during active area */
if (line < bitmap.viewport.h)
{
spr_ovr = 0x40;
}
break;
}
/* Adjust Y range back for zoomed sprites */
ypos >>= (reg[1] & 0x01);
/* Store sprite attributes for later processing */
object_info[count].ypos = ypos;
object_info[count].xpos = st[(i << 2) + 1];
object_info[count].attr = st[(i << 2) + 2];
object_info[count].size = st[(i << 2) + 3];
/* Increment Sprite count */
++count;
}
} }
while (++i < 32);
} }
while (++i < 32);
/* Update sprite count for next line */ /* Update sprite count for next line */
object_count = count; object_count = count;
@ -3642,6 +3657,7 @@ void parse_satb_tms(int line)
void parse_satb_m4(int line) void parse_satb_m4(int line)
{ {
int i = 0; int i = 0;
uint8 *st;
/* Sprite counter (8 max. per line) */ /* Sprite counter (8 max. per line) */
int count = 0; int count = 0;
@ -3649,11 +3665,8 @@ void parse_satb_m4(int line)
/* Y position */ /* Y position */
int ypos; int ypos;
/* Sprite height (8x8 by default) */ /* Sprite height (8x8 or 8x16) */
int height = 8; int height = 8 + ((reg[1] & 0x02) << 2);
/* Adjust height for 8x16 sprites */
height <<= ((reg[1] & 0x02) >> 1);
/* Sprite attribute table address mask */ /* Sprite attribute table address mask */
uint16 st_mask = ~0x3F80 ^ (reg[5] << 7); uint16 st_mask = ~0x3F80 ^ (reg[5] << 7);
@ -3665,7 +3678,7 @@ void parse_satb_m4(int line)
} }
/* Pointer to sprite attribute table */ /* Pointer to sprite attribute table */
uint8 *st = &vram[st_mask & 0x3F00]; st = &vram[st_mask & 0x3F00];
/* Parse Sprite Table (64 entries) */ /* Parse Sprite Table (64 entries) */
do do
@ -3674,7 +3687,7 @@ void parse_satb_m4(int line)
ypos = st[i]; ypos = st[i];
/* Check end of sprite list marker */ /* Check end of sprite list marker */
if(ypos == (bitmap.viewport.h + 16)) if (ypos == (bitmap.viewport.h + 16))
{ {
break; break;
} }
@ -3927,15 +3940,15 @@ void window_clip(unsigned int data, unsigned int sw)
int hp = (data & 0x1f); int hp = (data & 0x1f);
int hf = (data >> 7) & 1; int hf = (data >> 7) & 1;
/* Display width (16 or 20 columns) */
sw = 16 + (sw << 2);
/* Perform horizontal clipping; the results are applied in reverse /* Perform horizontal clipping; the results are applied in reverse
if the horizontal inversion flag is set if the horizontal inversion flag is set
*/ */
int a = hf; int a = hf;
int w = hf ^ 1; int w = hf ^ 1;
/* Display width (16 or 20 columns) */
sw = 16 + (sw << 2);
if(hp) if(hp)
{ {
if(hp > sw) if(hp > sw)
@ -4012,6 +4025,9 @@ void render_reset(void)
/* Clear color palettes */ /* Clear color palettes */
memset(pixel, 0, sizeof(pixel)); memset(pixel, 0, sizeof(pixel));
/* Clear pattern cache */
memset ((char *) bg_pattern_cache, 0, sizeof (bg_pattern_cache));
/* Reset Sprite infos */ /* Reset Sprite infos */
spr_ovr = spr_col = object_count = 0; spr_ovr = spr_col = object_count = 0;
} }
@ -4024,6 +4040,7 @@ void render_reset(void)
void render_line(int line) void render_line(int line)
{ {
int width = bitmap.viewport.w; int width = bitmap.viewport.w;
int x_offset;
/* Check display status */ /* Check display status */
if (reg[1] & 0x40) if (reg[1] & 0x40)
@ -4074,7 +4091,7 @@ void render_line(int line)
} }
/* Horizontal borders */ /* Horizontal borders */
int x_offset = bitmap.viewport.x; x_offset = bitmap.viewport.x;
if (x_offset > 0) if (x_offset > 0)
{ {
memset(&linebuf[0][0x20 - x_offset], 0x40, x_offset); memset(&linebuf[0][0x20 - x_offset], 0x40, x_offset);
@ -4094,8 +4111,10 @@ void blank_line(int line, int offset, int width)
void remap_line(int line) void remap_line(int line)
{ {
/* Line width */ /* Line width */
int x_offset = bitmap.viewport.x; int width = bitmap.viewport.w + (bitmap.viewport.x * 2);
int width = bitmap.viewport.w + (x_offset * 2);
/* Pixel line buffer */
uint8 *src = &linebuf[0][0x20 - bitmap.viewport.x];
/* Adjust line offset in framebuffer */ /* Adjust line offset in framebuffer */
line = (line + bitmap.viewport.y) % lines_per_frame; line = (line + bitmap.viewport.y) % lines_per_frame;
@ -4109,9 +4128,6 @@ void remap_line(int line)
line = (line * 2) + odd_frame; line = (line * 2) + odd_frame;
} }
/* Pixel line buffer */
uint8 *src = &linebuf[0][0x20 - x_offset];
/* NTSC Filter (only supported for 16-bit pixels rendering) */ /* NTSC Filter (only supported for 16-bit pixels rendering) */
#ifdef USE_16BPP_RENDERING #ifdef USE_16BPP_RENDERING
if (config.ntsc) if (config.ntsc)