mirror of
https://github.com/RaySollium99/picodrive.git
synced 2025-09-05 07:17:45 -04:00
vdp fifo, tentative fix for broken save/load
This commit is contained in:
parent
29d99d6bb8
commit
daf29df963
3 changed files with 78 additions and 39 deletions
|
@ -316,7 +316,10 @@ struct PicoVideo
|
||||||
unsigned char debug_p; // ... parsed: PVD_*
|
unsigned char debug_p; // ... parsed: PVD_*
|
||||||
unsigned char addr_u; // bit16 of .addr
|
unsigned char addr_u; // bit16 of .addr
|
||||||
unsigned char hint_cnt;
|
unsigned char hint_cnt;
|
||||||
unsigned char pad[0x0b];
|
unsigned char pad2;
|
||||||
|
unsigned short hv_latch; // latched hvcounter value
|
||||||
|
signed int fifo_cnt; // pending xfers for current FIFO queue entry
|
||||||
|
unsigned char pad[0x04];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PicoMisc
|
struct PicoMisc
|
||||||
|
@ -339,7 +342,7 @@ struct PicoMisc
|
||||||
unsigned char eeprom_slave; // EEPROM slave word for X24C02 and better SRAMs
|
unsigned char eeprom_slave; // EEPROM slave word for X24C02 and better SRAMs
|
||||||
unsigned char eeprom_status;
|
unsigned char eeprom_status;
|
||||||
unsigned char pad1; // was ym2612 status
|
unsigned char pad1; // was ym2612 status
|
||||||
unsigned short pad2; // 18 was dma_xfers
|
unsigned short dma_xfers; // 18 unused (was VDP DMA transfer count)
|
||||||
unsigned char eeprom_wb[2]; // EEPROM latch/write buffer
|
unsigned char eeprom_wb[2]; // EEPROM latch/write buffer
|
||||||
unsigned int frame_count; // 1c for movies and idle det
|
unsigned int frame_count; // 1c for movies and idle det
|
||||||
};
|
};
|
||||||
|
@ -856,6 +859,8 @@ extern int (*PicoDmaHook)(unsigned int source, int len, unsigned short **base, u
|
||||||
void PicoVideoFIFOSync(int cycles);
|
void PicoVideoFIFOSync(int cycles);
|
||||||
int PicoVideoFIFOHint(void);
|
int PicoVideoFIFOHint(void);
|
||||||
int PicoVideoFIFOWrite(int count, int byte_p, unsigned sr_mask, unsigned sr_flags);
|
int PicoVideoFIFOWrite(int count, int byte_p, unsigned sr_mask, unsigned sr_flags);
|
||||||
|
void PicoVideoSave(void);
|
||||||
|
void PicoVideoLoad(void);
|
||||||
|
|
||||||
// misc.c
|
// misc.c
|
||||||
PICO_INTERNAL_ASM void memcpy16bswap(unsigned short *dest, void *src, int count);
|
PICO_INTERNAL_ASM void memcpy16bswap(unsigned short *dest, void *src, int count);
|
||||||
|
|
|
@ -250,6 +250,8 @@ static int state_save(void *file)
|
||||||
CHECKED_WRITE_BUFF(CHUNK_ZRAM, PicoMem.zram);
|
CHECKED_WRITE_BUFF(CHUNK_ZRAM, PicoMem.zram);
|
||||||
CHECKED_WRITE_BUFF(CHUNK_CRAM, PicoMem.cram);
|
CHECKED_WRITE_BUFF(CHUNK_CRAM, PicoMem.cram);
|
||||||
CHECKED_WRITE_BUFF(CHUNK_MISC, Pico.m);
|
CHECKED_WRITE_BUFF(CHUNK_MISC, Pico.m);
|
||||||
|
|
||||||
|
PicoVideoSave();
|
||||||
CHECKED_WRITE_BUFF(CHUNK_VIDEO, Pico.video);
|
CHECKED_WRITE_BUFF(CHUNK_VIDEO, Pico.video);
|
||||||
|
|
||||||
z80_pack(buff_z80);
|
z80_pack(buff_z80);
|
||||||
|
@ -433,7 +435,11 @@ static int state_load(void *file)
|
||||||
case CHUNK_CRAM: CHECKED_READ_BUFF(PicoMem.cram); break;
|
case CHUNK_CRAM: CHECKED_READ_BUFF(PicoMem.cram); break;
|
||||||
case CHUNK_VSRAM: CHECKED_READ_BUFF(PicoMem.vsram); break;
|
case CHUNK_VSRAM: CHECKED_READ_BUFF(PicoMem.vsram); break;
|
||||||
case CHUNK_MISC: CHECKED_READ_BUFF(Pico.m); break;
|
case CHUNK_MISC: CHECKED_READ_BUFF(Pico.m); break;
|
||||||
case CHUNK_VIDEO: CHECKED_READ_BUFF(Pico.video); break;
|
case CHUNK_VIDEO:
|
||||||
|
CHECKED_READ_BUFF(Pico.video);
|
||||||
|
PicoVideoLoad();
|
||||||
|
break;
|
||||||
|
|
||||||
case CHUNK_IOPORTS: CHECKED_READ_BUFF(PicoMem.ioports); break;
|
case CHUNK_IOPORTS: CHECKED_READ_BUFF(PicoMem.ioports); break;
|
||||||
case CHUNK_PSG: CHECKED_READ2(28*4, sn76496_regs); break;
|
case CHUNK_PSG: CHECKED_READ2(28*4, sn76496_regs); break;
|
||||||
case CHUNK_FM:
|
case CHUNK_FM:
|
||||||
|
|
100
pico/videoport.c
100
pico/videoport.c
|
@ -14,7 +14,6 @@
|
||||||
extern const unsigned char hcounts_32[];
|
extern const unsigned char hcounts_32[];
|
||||||
extern const unsigned char hcounts_40[];
|
extern const unsigned char hcounts_40[];
|
||||||
|
|
||||||
static unsigned hvlatch; // latched hvcounter value
|
|
||||||
static int blankline; // display disabled for this line
|
static int blankline; // display disabled for this line
|
||||||
|
|
||||||
int (*PicoDmaHook)(unsigned int source, int len, unsigned short **base, unsigned int *mask) = NULL;
|
int (*PicoDmaHook)(unsigned int source, int len, unsigned short **base, unsigned int *mask) = NULL;
|
||||||
|
@ -70,7 +69,7 @@ const unsigned char vdpcyc2sl_32[] = { // 68k cycles/4 since HINT to slot #
|
||||||
14,14,14,14,14,14,14,14,15,16,16,16,16,16,16,16,
|
14,14,14,14,14,14,14,14,15,16,16,16,16,16,16,16,
|
||||||
};
|
};
|
||||||
const unsigned char vdpsl2cyc_32[] = { // slot # to 68k cycles/4 since HINT
|
const unsigned char vdpsl2cyc_32[] = { // slot # to 68k cycles/4 since HINT
|
||||||
0, 9, 19, 30, 35, 41, 52, 58, 64, 75, 81, 87, 98,104,110,120,121,123,123
|
0, 9, 19, 30, 35, 41, 52, 58, 64, 75, 81, 87, 98,104,110,120,121,123
|
||||||
};
|
};
|
||||||
|
|
||||||
// VDP transfer slots in active display 40col mode. 1 slot is 488/210 = 2.3238
|
// VDP transfer slots in active display 40col mode. 1 slot is 488/210 = 2.3238
|
||||||
|
@ -88,33 +87,37 @@ const unsigned char vdpcyc2sl_40[] = { // 68k cycles/4 since HINT to slot #
|
||||||
16,16,16,16,16,16,16,16,17,18,18,18,18,18,18,18,
|
16,16,16,16,16,16,16,16,17,18,18,18,18,18,18,18,
|
||||||
};
|
};
|
||||||
const unsigned char vdpsl2cyc_40[] = { // slot # to 68k cycles/4 since HINT
|
const unsigned char vdpsl2cyc_40[] = { // slot # to 68k cycles/4 since HINT
|
||||||
0, 13, 28, 33, 37, 47, 51, 56, 65, 70, 74, 84, 88, 93,102,107,112,120,121,123,123
|
0, 13, 28, 33, 37, 47, 51, 56, 65, 70, 74, 84, 88, 93,102,107,112,120,121,123
|
||||||
};
|
};
|
||||||
|
|
||||||
// NB code assumes fifo_* arrays have size 2^n
|
// NB code assumes fifo_* arrays have size 2^n
|
||||||
// last transferred FIFO data, ...x = index XXX currently only CPU
|
// last transferred FIFO data, ...x = index XXX currently only CPU
|
||||||
static short fifo_data[4], fifo_dx;
|
static short fifo_data[4], fifo_dx; // XXX must go into save?
|
||||||
|
|
||||||
// queued FIFO transfers, ...x = index, ...l = queue length
|
// queued FIFO transfers, ...x = index, ...l = queue length
|
||||||
// each entry has 2 values: [n]>>2=#writes, [n]&3=flags:2=DMA fill 1=byte access
|
// each entry has 2 values: [n]>>2=#writes, [n]&3=flags:2=DMA fill 1=byte access
|
||||||
static int fifo_queue[8], fifo_qx, fifo_ql;
|
static int fifo_queue[8], fifo_qx, fifo_ql; // XXX must go into save?
|
||||||
|
|
||||||
signed int fifo_cnt; // pending slots for current queue entry
|
|
||||||
unsigned short fifo_slot; // last executed slot in current scanline
|
|
||||||
unsigned int fifo_total; // total# of pending FIFO entries
|
unsigned int fifo_total; // total# of pending FIFO entries
|
||||||
|
|
||||||
|
unsigned short fifo_slot; // last executed slot in current scanline
|
||||||
|
|
||||||
// do the FIFO math
|
// do the FIFO math
|
||||||
static __inline int AdvanceFIFOEntry(int slots)
|
static __inline int AdvanceFIFOEntry(struct PicoVideo *pv, int slots)
|
||||||
{
|
{
|
||||||
int l = slots, b = fifo_queue[fifo_qx&7] & 1;
|
int l = slots, b = fifo_queue[fifo_qx&7] & 1;
|
||||||
|
|
||||||
if (l > fifo_cnt)
|
if (l > pv->fifo_cnt)
|
||||||
l = fifo_cnt;
|
l = pv->fifo_cnt;
|
||||||
fifo_total -= ((fifo_cnt & b) + l) >> b;
|
fifo_total -= ((pv->fifo_cnt & b) + l) >> b;
|
||||||
fifo_cnt -= l;
|
pv->fifo_cnt -= l;
|
||||||
|
|
||||||
if (fifo_cnt == 0) {
|
if (pv->fifo_cnt == 0) {
|
||||||
fifo_qx ++, fifo_ql --;
|
if (fifo_ql)
|
||||||
fifo_cnt= (fifo_queue[fifo_qx&7] >> 2) << (fifo_queue[fifo_qx&7] & 1);
|
fifo_qx ++, fifo_ql --;
|
||||||
|
if (fifo_ql)
|
||||||
|
pv->fifo_cnt= (fifo_queue[fifo_qx&7] >> 2) << (fifo_queue[fifo_qx&7] & 1);
|
||||||
|
else
|
||||||
|
fifo_total = 0;
|
||||||
}
|
}
|
||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
@ -129,7 +132,7 @@ static __inline int GetFIFOSlot(struct PicoVideo *pv, int cycles)
|
||||||
else return (cycles * vdpcyc2sl_bl[h40] + cycles) >> 16;
|
else return (cycles * vdpcyc2sl_bl[h40] + cycles) >> 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int GetFIFOCycles(struct PicoVideo *pv, int slot)
|
static __inline int GetFIFOCycles(struct PicoVideo *pv, int slot)
|
||||||
{
|
{
|
||||||
int active = !(pv->status & SR_VB) && (pv->reg[1] & 0x40);
|
int active = !(pv->status & SR_VB) && (pv->reg[1] & 0x40);
|
||||||
int h40 = pv->reg[12] & 1;
|
int h40 = pv->reg[12] & 1;
|
||||||
|
@ -146,13 +149,12 @@ void PicoVideoFIFOSync(int cycles)
|
||||||
int slots, done;
|
int slots, done;
|
||||||
|
|
||||||
// calculate #slots since last executed slot
|
// calculate #slots since last executed slot
|
||||||
slots = GetFIFOSlot(pv, cycles);
|
slots = GetFIFOSlot(pv, cycles) - fifo_slot;
|
||||||
slots -= fifo_slot;
|
|
||||||
|
|
||||||
// advance FIFO queue by #done slots
|
// advance FIFO queue by #done slots
|
||||||
done = slots;
|
done = slots;
|
||||||
while (done > 0 && fifo_ql) {
|
while (done > 0 && pv->fifo_cnt) {
|
||||||
int l = AdvanceFIFOEntry(done);
|
int l = AdvanceFIFOEntry(pv, done);
|
||||||
fifo_slot += l;
|
fifo_slot += l;
|
||||||
done -= l;
|
done -= l;
|
||||||
}
|
}
|
||||||
|
@ -181,7 +183,7 @@ int PicoVideoFIFODrain(int level, int cycles)
|
||||||
int b = fifo_queue[fifo_qx&7] & 1;
|
int b = fifo_queue[fifo_qx&7] & 1;
|
||||||
int cnt = (fifo_total-level) << b;
|
int cnt = (fifo_total-level) << b;
|
||||||
int last = fifo_slot;
|
int last = fifo_slot;
|
||||||
int slot = (fifo_cnt<cnt?fifo_cnt:cnt) + last; // target slot
|
int slot = (pv->fifo_cnt<cnt?pv->fifo_cnt:cnt) + last; // target slot
|
||||||
unsigned ocyc = cycles;
|
unsigned ocyc = cycles;
|
||||||
|
|
||||||
if (slot > maxsl) {
|
if (slot > maxsl) {
|
||||||
|
@ -196,7 +198,7 @@ int PicoVideoFIFODrain(int level, int cycles)
|
||||||
}
|
}
|
||||||
burn += cycles - ocyc;
|
burn += cycles - ocyc;
|
||||||
|
|
||||||
AdvanceFIFOEntry(slot - last);
|
AdvanceFIFOEntry(pv, slot - last);
|
||||||
}
|
}
|
||||||
|
|
||||||
// release CPU and terminate DMA if FIFO isn't blocking the bus anymore
|
// release CPU and terminate DMA if FIFO isn't blocking the bus anymore
|
||||||
|
@ -249,7 +251,7 @@ int PicoVideoFIFOWrite(int count, int flags, unsigned sr_mask,unsigned sr_flags)
|
||||||
// update FIFO state if it was empty
|
// update FIFO state if it was empty
|
||||||
if (fifo_total == 0 && count) {
|
if (fifo_total == 0 && count) {
|
||||||
fifo_slot = GetFIFOSlot(pv, lc);
|
fifo_slot = GetFIFOSlot(pv, lc);
|
||||||
fifo_cnt = count << (flags&1);
|
pv->fifo_cnt = count << (flags&1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// create xfer queue entry
|
// create xfer queue entry
|
||||||
|
@ -263,8 +265,8 @@ int PicoVideoFIFOWrite(int count, int flags, unsigned sr_mask,unsigned sr_flags)
|
||||||
if ((pv->status & (PVS_CPUWR|PVS_DMAFILL)) == PVS_CPUWR)
|
if ((pv->status & (PVS_CPUWR|PVS_DMAFILL)) == PVS_CPUWR)
|
||||||
burn = PicoVideoFIFODrain(4, lc);
|
burn = PicoVideoFIFODrain(4, lc);
|
||||||
else if (fifo_queue[fifo_qx&7]&2) {
|
else if (fifo_queue[fifo_qx&7]&2) {
|
||||||
// if interrupting a DMA fill terminate it
|
// if interrupting a DMA fill terminate it XXX wrong, changes fill data
|
||||||
AdvanceFIFOEntry(fifo_cnt);
|
AdvanceFIFOEntry(pv, pv->fifo_cnt);
|
||||||
pv->status &= ~PVS_DMAFILL;
|
pv->status &= ~PVS_DMAFILL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -699,9 +701,9 @@ PICO_INTERNAL_ASM void PicoVideoWrite(unsigned int a,unsigned short d)
|
||||||
// try avoiding the sync..
|
// try avoiding the sync..
|
||||||
if (Pico.m.scanline < (pvid->reg[1]&0x08 ? 240 : 224) && (pvid->reg[1]&0x40) &&
|
if (Pico.m.scanline < (pvid->reg[1]&0x08 ? 240 : 224) && (pvid->reg[1]&0x40) &&
|
||||||
!(!pvid->pending &&
|
!(!pvid->pending &&
|
||||||
((pvid->command & 0xc00000f0) == 0x40000010 && PicoMem.vsram[pvid->addr>>1] == d))
|
((pvid->command & 0xc00000f0) == 0x40000010 && PicoMem.vsram[pvid->addr>>1] == (d & 0x7ff)))
|
||||||
)
|
)
|
||||||
DrawSync(0);
|
DrawSync(SekCyclesDone() - Pico.t.m68c_line_start <= 488-440);
|
||||||
|
|
||||||
if (pvid->pending) {
|
if (pvid->pending) {
|
||||||
CommandChange();
|
CommandChange();
|
||||||
|
@ -736,7 +738,7 @@ PICO_INTERNAL_ASM void PicoVideoWrite(unsigned int a,unsigned short d)
|
||||||
CommandChange();
|
CommandChange();
|
||||||
// Check for dma:
|
// Check for dma:
|
||||||
if (d & 0x80) {
|
if (d & 0x80) {
|
||||||
DrawSync(0);
|
DrawSync(SekCyclesDone() - Pico.t.m68c_line_start <= 488-390);
|
||||||
CommandDma();
|
CommandDma();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -747,7 +749,6 @@ PICO_INTERNAL_ASM void PicoVideoWrite(unsigned int a,unsigned short d)
|
||||||
// Register write:
|
// Register write:
|
||||||
int num=(d>>8)&0x1f;
|
int num=(d>>8)&0x1f;
|
||||||
int dold=pvid->reg[num];
|
int dold=pvid->reg[num];
|
||||||
int skip=0;
|
|
||||||
pvid->type=0; // register writes clear command (else no Sega logo in Golden Axe II)
|
pvid->type=0; // register writes clear command (else no Sega logo in Golden Axe II)
|
||||||
if (num > 0x0a && !(pvid->reg[1]&4)) {
|
if (num > 0x0a && !(pvid->reg[1]&4)) {
|
||||||
elprintf(EL_ANOMALY, "%02x written to reg %02x in SMS mode @ %06x", d, num, SekPc);
|
elprintf(EL_ANOMALY, "%02x written to reg %02x in SMS mode @ %06x", d, num, SekPc);
|
||||||
|
@ -755,16 +756,14 @@ PICO_INTERNAL_ASM void PicoVideoWrite(unsigned int a,unsigned short d)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (num == 0 && !(pvid->reg[0]&2) && (d&2))
|
if (num == 0 && !(pvid->reg[0]&2) && (d&2))
|
||||||
hvlatch = PicoVideoRead(0x08);
|
pvid->hv_latch = PicoVideoRead(0x08);
|
||||||
if (num == 1 && ((pvid->reg[1]^d)&0x40)) {
|
if (num == 1 && ((pvid->reg[1]^d)&0x40)) {
|
||||||
PicoVideoFIFOMode(d & 0x40);
|
PicoVideoFIFOMode(d & 0x40);
|
||||||
// handle line blanking before line rendering
|
// handle line blanking before line rendering
|
||||||
if (SekCyclesDone() - Pico.t.m68c_line_start <= 488-390) {
|
if (SekCyclesDone() - Pico.t.m68c_line_start <= 488-390)
|
||||||
skip = 1;
|
|
||||||
blankline = d&0x40 ? -1 : Pico.m.scanline;
|
blankline = d&0x40 ? -1 : Pico.m.scanline;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
DrawSync(skip);
|
DrawSync(SekCyclesDone() - Pico.t.m68c_line_start <= 488-390);
|
||||||
pvid->reg[num]=(unsigned char)d;
|
pvid->reg[num]=(unsigned char)d;
|
||||||
switch (num)
|
switch (num)
|
||||||
{
|
{
|
||||||
|
@ -904,7 +903,7 @@ PICO_INTERNAL_ASM unsigned int PicoVideoRead(unsigned int a)
|
||||||
|
|
||||||
d = (SekCyclesDone() - Pico.t.m68c_line_start) & 0x1ff; // FIXME
|
d = (SekCyclesDone() - Pico.t.m68c_line_start) & 0x1ff; // FIXME
|
||||||
if (Pico.video.reg[0]&2)
|
if (Pico.video.reg[0]&2)
|
||||||
d = hvlatch;
|
d = Pico.video.hv_latch;
|
||||||
else if (Pico.video.reg[12]&1)
|
else if (Pico.video.reg[12]&1)
|
||||||
d = hcounts_40[d] | (Pico.video.v_counter << 8);
|
d = hcounts_40[d] | (Pico.video.v_counter << 8);
|
||||||
else d = hcounts_32[d] | (Pico.video.v_counter << 8);
|
else d = hcounts_32[d] | (Pico.video.v_counter << 8);
|
||||||
|
@ -970,4 +969,33 @@ unsigned char PicoVideoRead8HV_L(void)
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PicoVideoSave(void)
|
||||||
|
{
|
||||||
|
struct PicoVideo *pv = &Pico.video;
|
||||||
|
int l, x;
|
||||||
|
|
||||||
|
// account for all outstanding xfers XXX kludge, entry attr's not saved
|
||||||
|
for (l = fifo_ql, x = fifo_qx + l-1; l > 1; l--, x--)
|
||||||
|
pv->fifo_cnt += (fifo_queue[x&7] >> 2) << (fifo_queue[x&7] & 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PicoVideoLoad(void)
|
||||||
|
{
|
||||||
|
struct PicoVideo *pv = &Pico.video;
|
||||||
|
int l;
|
||||||
|
|
||||||
|
// convert former dma_xfers (why was this in PicoMisc anyway?)
|
||||||
|
if (Pico.m.dma_xfers) {
|
||||||
|
pv->fifo_cnt = Pico.m.dma_xfers * (pv->type == 1 ? 2 : 1);
|
||||||
|
fifo_total = Pico.m.dma_xfers;
|
||||||
|
Pico.m.dma_xfers = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// rebuild SAT cache XXX wrong since cache and memory can differ
|
||||||
|
for (l = 0; l < 80; l++) {
|
||||||
|
*((u16 *)VdpSATCache + 2*l ) = PicoMem.vram[(sat>>1) + l*4 ];
|
||||||
|
*((u16 *)VdpSATCache + 2*l+1) = PicoMem.vram[(sat>>1) + l*4 + 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// vim:shiftwidth=2:ts=2:expandtab
|
// vim:shiftwidth=2:ts=2:expandtab
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue