return d;\r
}\r
\r
-#if 0\r
-// calculate the number of cycles 68k->VDP dma operation would take\r
-static int DmaSlowBurn(int len)\r
-{\r
- // test: Legend of Galahad, Time Killers\r
- int burn,maxlen,line=Pico.m.scanline;\r
-\r
- if(line == -1) line=vcounts[SekCyclesDone()>>8];\r
- maxlen=(224-line)*18;\r
- if(len <= maxlen)\r
- burn = len*(((488<<8)/18))>>8;\r
- else {\r
- burn = maxlen*(((488<<8)/18))>>8;\r
- burn += (len-maxlen)*(((488<<8)/180))>>8;\r
- }\r
-\r
- return burn;\r
-}\r
-#endif\r
-\r
static int GetDmaLength()\r
{\r
struct PicoVideo *pvid=&Pico.video;\r
u16 *pd=0, *pdend, *r;\r
unsigned int a=Pico.video.addr, a2, d;\r
unsigned char inc=Pico.video.reg[0xf];\r
- unsigned int source; // , burn;\r
+ unsigned int source;\r
\r
source =Pico.video.reg[0x15]<<1;\r
source|=Pico.video.reg[0x16]<<9;\r
Pico.video.type, source, a, len, inc, (Pico.video.status&8)||!(Pico.video.reg[1]&0x40),\r
Pico.m.scanline, SekCyclesDone(), SekPc);\r
\r
+ if(Pico.m.scanline != -1) {\r
+ Pico.m.dma_bytes += len;\r
+ SekSetCyclesLeft(SekCyclesLeft - CheckDMA());\r
+ } else {\r
+ // be approximate in non-accurate mode\r
+ SekSetCyclesLeft(SekCyclesLeft - (len*(((488<<8)/167))>>8));\r
+ }\r
+\r
if ((source&0xe00000)==0xe00000) { pd=(u16 *)(Pico.ram+(source&0xfffe)); pdend=(u16 *)(Pico.ram+0x10000); } // Ram\r
- else if(source<Pico.romsize) { pd=(u16 *)(Pico.rom+(source&~1)); pdend=(u16 *)(Pico.rom+Pico.romsize); } // Rom\r
- else return; // Invalid source address\r
-\r
-#if 0\r
- // CPU is stopped during DMA, so we burn some cycles to compensate that\r
- if((Pico.video.status&8)||!(Pico.video.reg[1]&0x40)) { // vblank?\r
- burn = (len*(((488<<8)/167))>>8); // very approximate\r
- if(!(Pico.video.status&8)) burn+=burn>>1; // a hack for Legend of Galahad\r
- } else burn = DmaSlowBurn(len);\r
- SekCyclesBurn(burn);\r
-#else\r
- Pico.m.dma_bytes += len;\r
-#endif\r
- //if(!(Pico.video.status&8))\r
-// SekEndRun(0);\r
- //Pico.m.dma_endcycles = 0;//SekCyclesLeft;\r
- //Pico.m.dma_endcycles -= Pico.m.dma_endcycles>>3; // hack\r
- SekSetCyclesLeft(SekCyclesLeft - CheckDMA());\r
-// CheckDMA();\r
-// dprintf("DmaSlow burn: %i @ %06x", burn, SekPc);\r
+ else if(PicoMCD & 1) {\r
+ if(source<0x20000) { pd=(u16 *)(Pico_mcd->bios+(source&~1)); pdend=(u16 *)(Pico_mcd->bios+0x20000); } // Bios area\r
+ else { dprintf("unsupported src"); return; } // Invalid source address\r
+ } else {\r
+ if(source<Pico.romsize) { pd=(u16 *)(Pico.rom+(source&~1)); pdend=(u16 *)(Pico.rom+Pico.romsize); } // Rom\r
+ else { dprintf("invalid dma src"); return; } // Invalid source address\r
+ }\r
\r
switch (Pico.video.type)\r
{\r
{\r
u32 d=0;\r
a &= 0x3e;\r
- dprintf("m68k_regs r%2i: [%02x] @%06x", realsize&~1, a+(realsize&1), SekPc);\r
+ // dprintf("m68k_regs r%2i: [%02x] @%06x", realsize&~1, a+(realsize&1), SekPc);\r
\r
switch (a) {\r
+ case 0:\r
+ d = ((Pico_mcd->s68k_regs[0x33]<<13)&0x8000) | Pico_mcd->m68k_regs[1]; // here IFL2 is always 0, just like in Gens\r
+ goto end;\r
case 2:\r
- d = (Pico_mcd->m68k_regs[a]<<8) | Pico_mcd->m68k_regs[a+1] | 1; // for now 2M to m68k\r
+ d = (Pico_mcd->s68k_regs[a]<<8) | (Pico_mcd->s68k_regs[a+1]&0xc7);\r
goto end;\r
case 8:\r
dprintf("m68k host data read");\r
\r
end:\r
\r
- dprintf("ret = %04x", d);\r
+ // dprintf("ret = %04x", d);\r
return d;\r
}\r
\r
static void m68k_reg_write8(u32 a, u32 d, int realsize)\r
{\r
a &= 0x3f;\r
- dprintf("m68k_regs w%2i: [%02x] %02x @%06x", realsize, a, d, SekPc);\r
+ // dprintf("m68k_regs w%2i: [%02x] %02x @%06x", realsize, a, d, SekPc);\r
\r
switch (a) {\r
case 0:\r
+ d &= 1;\r
if ((d&1) && (Pico_mcd->s68k_regs[0x33]&(1<<2))) { dprintf("m68k: s68k irq 2"); SekInterruptS68k(2); }\r
break;\r
case 1:\r
+ d &= 3;\r
if (!(d&1)) PicoMCD |= 2; // reset pending, needed to be sure we fetch the right vectors on reset\r
if ( (Pico_mcd->m68k_regs[1]&1) != (d&1)) dprintf("m68k: s68k reset %i", !(d&1));\r
if ( (Pico_mcd->m68k_regs[1]&2) != (d&2)) dprintf("m68k: s68k brq %i", (d&2)>>1);\r
if (/*!(Pico_mcd->m68k_regs[1]&1) &&*/ (PicoMCD&2) && (d&3)==1) {\r
SekResetS68k(); // S68k comes out of RESET or BRQ state\r
PicoMCD&=~2;\r
- dprintf("m68k: resetting s68k");\r
+ dprintf("m68k: resetting s68k, cycles=%i", SekCyclesLeft);\r
}\r
break;\r
+ case 2:\r
+ Pico_mcd->s68k_regs[2] = d; // really use s68k side register\r
+ return;\r
case 3:\r
- if ((Pico_mcd->m68k_regs[3]>>6) != ((d>>6)&3))\r
- dprintf("m68k: prg bank: %i -> %i", (Pico_mcd->m68k_regs[a]>>6), ((d>>6)&3));\r
- if ((Pico_mcd->m68k_regs[3]&4) != (d&4)) dprintf("m68k: ram mode %i mbit", (d&4) ? 1 : 2);\r
- if ((Pico_mcd->m68k_regs[3]&2) != (d&2)) dprintf("m68k: %s", (d&4) ? ((d&2) ? "word swap req" : "noop?") :\r
- ((d&2) ? "word ram to s68k" : "word ram to m68k"));\r
- break;\r
+ d &= 0xc2;\r
+ if ((Pico_mcd->s68k_regs[3]>>6) != ((d>>6)&3))\r
+ dprintf("m68k: prg bank: %i -> %i", (Pico_mcd->s68k_regs[a]>>6), ((d>>6)&3));\r
+ //if ((Pico_mcd->s68k_regs[3]&4) != (d&4)) dprintf("m68k: ram mode %i mbit", (d&4) ? 1 : 2);\r
+ //if ((Pico_mcd->s68k_regs[3]&2) != (d&2)) dprintf("m68k: %s", (d&4) ? ((d&2) ? "word swap req" : "noop?") :\r
+ // ((d&2) ? "word ram to s68k" : "word ram to m68k"));\r
+ d |= Pico_mcd->s68k_regs[3]&0x1d;\r
+ if (d & 2) d &= ~1; // returning word RAM to s68k\r
+ Pico_mcd->s68k_regs[3] = d; // really use s68k side register\r
+ return;\r
case 0xe:\r
- dprintf("m68k: comm flag: %02x", d);\r
+ //dprintf("m68k: comm flag: %02x", d);\r
\r
- dprintf("s68k @ %06x", SekPcS68k);\r
+ //dprintf("s68k @ %06x", SekPcS68k);\r
\r
Pico_mcd->s68k_regs[0xe] = d;\r
break;\r
}\r
\r
- if ((a&0xff) == 0x10) {\r
+ if (a < 0x10) {\r
+ Pico_mcd->m68k_regs[a] = (u8) d;\r
+ return;\r
+ }\r
+\r
+ if ((a&0xf0) == 0x10) {\r
Pico_mcd->s68k_regs[a] = d;\r
+ return;\r
}\r
\r
if (a >= 0x20 || (a >= 0xa && a <= 0xd) || a == 0x0f)\r
dprintf("m68k: invalid write?");\r
-\r
- if (a < 0x10)\r
- Pico_mcd->m68k_regs[a] = (u8) d;\r
}\r
\r
\r
u32 d=0;\r
a &= 0x1fe;\r
\r
- dprintf("s68k_regs r%2i: [%02x] @ %06x", realsize&~1, a+(realsize&1), SekPcS68k);\r
+ // dprintf("s68k_regs r%2i: [%02x] @ %06x", realsize&~1, a+(realsize&1), SekPcS68k);\r
\r
switch (a) {\r
case 0:\r
d = 1; goto end; // ver = 0, not in reset state\r
+ case 2:\r
+ d = (Pico_mcd->s68k_regs[a]<<8) | (Pico_mcd->s68k_regs[a+1]&0x1f);\r
+ goto end;\r
case 6:\r
d = CDC_Read_Reg();\r
goto end;\r
\r
end:\r
\r
- dprintf("ret = %04x", d);\r
+ // dprintf("ret = %04x", d);\r
\r
return d;\r
}\r
static void s68k_reg_write8(u32 a, u32 d, int realsize)\r
{\r
a &= 0x1ff;\r
- dprintf("s68k_regs w%2i: [%02x] %02x @ %06x", realsize, a, d, SekPcS68k);\r
+ //dprintf("s68k_regs w%2i: [%02x] %02x @ %06x", realsize, a, d, SekPcS68k);\r
\r
// TODO: review against Gens\r
switch (a) {\r
+ case 2:\r
+ return; // only m68k can change WP\r
+ case 3:\r
+ d &= 0x1d;\r
+ d |= Pico_mcd->s68k_regs[3]&0xc2;\r
+ if (d&1) d &= ~2; // returning word RAM to m68k\r
+ break;\r
case 4:\r
dprintf("s68k CDC dest: %x", d&7);\r
Pico_mcd->s68k_regs[4] = (Pico_mcd->s68k_regs[4]&0xC0) | (d&7); // CDC mode\r
case 0x34: // fader\r
Pico_mcd->s68k_regs[a] = (u8) d & 0x7f;\r
return;\r
- case 0x37:\r
- if ((d&4) && !(Pico_mcd->s68k_regs[0x37]&4)) {\r
+ case 0x36:\r
+ return; // d/m bit is unsetable\r
+ case 0x37: {\r
+ u32 d_old = Pico_mcd->s68k_regs[0x37];\r
+ Pico_mcd->s68k_regs[0x37] = d&7;\r
+ if ((d&4) && !(d_old&4)) {\r
CDD_Export_Status();\r
// counter75hz = 0; // ???\r
}\r
- break;\r
+ return;\r
+ }\r
case 0x4b:\r
Pico_mcd->s68k_regs[a] = (u8) d;\r
CDD_Import_Command();\r
\r
if ((a&0xe700e0)==0xc00000) { d=PicoVideoRead(a); goto end; }\r
\r
- if ((a&0xffffc0)==0xa12000) { d=m68k_reg_read16(a, realsize); goto end; }\r
+ if ((a&0xffffc0)==0xa12000) {\r
+ d=m68k_reg_read16(a, realsize);\r
+ goto end;\r
+ }\r
\r
d = UnusualRead16(a, realsize);\r
\r
\r
// prg RAM\r
if ((a&0xfe0000)==0x020000) {\r
- u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->m68k_regs[3]>>6];\r
+ u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6];\r
d = *(prg_bank+((a^1)&0x1ffff));\r
goto end;\r
}\r
\r
if ((a&0xff4000)==0xa00000) { d=z80Read8(a); goto end; } // Z80 Ram\r
\r
+ if ((a&0xffffc0)==0xa12000)\r
+ dprintf("m68k_regs r8: [%02x] @%06x", a&0x3f, SekPc);\r
+\r
d=OtherRead16(a&~1, 8|(a&1)); if ((a&1)==0) d>>=8;\r
\r
+ if ((a&0xffffc0)==0xa12000)\r
+ dprintf("ret = %02x", (u8)d);\r
+\r
end:\r
\r
#ifdef __debug_io\r
\r
// prg RAM\r
if ((a&0xfe0000)==0x020000) {\r
- u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->m68k_regs[3]>>6];\r
+ u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6];\r
d = *(u16 *)(prg_bank+(a&0x1fffe));\r
goto end;\r
}\r
\r
+ if ((a&0xffffc0)==0xa12000)\r
+ dprintf("m68k_regs r16: [%02x] @%06x", a&0x3f, SekPc);\r
+\r
d = (u16)OtherRead16(a, 16);\r
\r
+ if ((a&0xffffc0)==0xa12000)\r
+ dprintf("ret = %04x", d);\r
+\r
end:\r
\r
#ifdef __debug_io\r
\r
// prg RAM\r
if ((a&0xfe0000)==0x020000) {\r
- u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->m68k_regs[3]>>6];\r
+ u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6];\r
u16 *pm=(u16 *)(prg_bank+(a&0x1fffe));\r
d = (pm[0]<<16)|pm[1];\r
goto end;\r
}\r
\r
+ if ((a&0xffffc0)==0xa12000)\r
+ dprintf("m68k_regs r32: [%02x] @%06x", a&0x3f, SekPc);\r
+\r
d = (OtherRead16(a, 32)<<16)|OtherRead16(a+2, 32);\r
\r
+ if ((a&0xffffc0)==0xa12000)\r
+ dprintf("ret = %08x", d);\r
+\r
end:\r
#ifdef __debug_io\r
dprintf("r32: %06x, %08x @%06x", a&0xffffff, d, SekPc);\r
\r
// prg RAM\r
if ((a&0xfe0000)==0x020000) {\r
- u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->m68k_regs[3]>>6];\r
+ u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6];\r
u8 *pm=(u8 *)(prg_bank+((a^1)&0x1ffff));\r
*pm=d;\r
return;\r
}\r
\r
+ if ((a&0xffffc0)==0xa12000)\r
+ dprintf("m68k_regs w8: [%02x] %02x @%06x", a&0x3f, d, SekPc);\r
+\r
OtherWrite8(a,d,8);\r
}\r
\r
\r
// prg RAM\r
if ((a&0xfe0000)==0x020000) {\r
- u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->m68k_regs[3]>>6];\r
+ u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6];\r
*(u16 *)(prg_bank+(a&0x1fffe))=d;\r
return;\r
}\r
\r
+ if ((a&0xffffc0)==0xa12000)\r
+ dprintf("m68k_regs w16: [%02x] %04x @%06x", a&0x3f, d, SekPc);\r
\r
OtherWrite16(a,d);\r
}\r
\r
// prg RAM\r
if ((a&0xfe0000)==0x020000) {\r
- u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->m68k_regs[3]>>6];\r
+ u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6];\r
u16 *pm=(u16 *)(prg_bank+(a&0x1fffe));\r
pm[0]=(u16)(d>>16); pm[1]=(u16)d;\r
return;\r
}\r
\r
+ // word RAM\r
+ if (a!=0x200000 && (a&0xfc0000)==0x200000) // tmp hack\r
+ return;\r
+\r
+\r
+ if ((a&0xffffc0)==0xa12000)\r
+ dprintf("m68k_regs w32: [%02x] %08x @%06x", a&0x3f, d, SekPc);\r
\r
OtherWrite16(a, (u16)(d>>16));\r
OtherWrite16(a+2,(u16)d);\r
\r
// regs\r
if ((a&0xfffe00) == 0xff8000) {\r
+ dprintf("s68k_regs r8: [%02x] @ %06x", a&0x1ff, SekPcS68k);\r
d = s68k_reg_read16(a&~1, 8|(a&1)); if ((a&1)==0) d>>=8;\r
+ dprintf("ret = %02x", (u8)d);\r
goto end;\r
}\r
\r
\r
// regs\r
if ((a&0xfffe00) == 0xff8000) {\r
+ dprintf("s68k_regs r16: [%02x] @ %06x", a&0x1fe, SekPcS68k);\r
d = s68k_reg_read16(a, 16);\r
+ dprintf("ret = %04x", d);\r
goto end;\r
}\r
\r
\r
// regs\r
if ((a&0xfffe00) == 0xff8000) {\r
+ dprintf("s68k_regs r32: [%02x] @ %06x", a&0x1fe, SekPcS68k);\r
d = (s68k_reg_read16(a, 32)<<16)|s68k_reg_read16(a+2, 32);\r
+ dprintf("ret = %08x", d);\r
goto end;\r
}\r
\r
return;\r
}\r
\r
+ if (a != 0xff0011 && (a&0xff8000) == 0xff0000) // PCM hack\r
+ return;\r
+\r
// regs\r
if ((a&0xfffe00) == 0xff8000) {\r
+ dprintf("s68k_regs w8: [%02x] %02x @ %06x", a&0x1ff, d, SekPcS68k);\r
s68k_reg_write8(a,d,8);\r
return;\r
}\r
\r
// regs\r
if ((a&0xfffe00) == 0xff8000) {\r
+ dprintf("s68k_regs w16: [%02x] %04x @ %06x", a&0x1ff, d, SekPcS68k);\r
s68k_reg_write8(a, d>>8, 16);\r
s68k_reg_write8(a+1,d&0xff, 16);\r
return;\r
\r
// regs\r
if ((a&0xfffe00) == 0xff8000) {\r
+ dprintf("s68k_regs w32: [%02x] %08x @ %06x", a&0x1ff, d, SekPcS68k);\r
s68k_reg_write8(a, d>>24, 32);\r
s68k_reg_write8(a+1,(d>>16)&0xff, 32);\r
s68k_reg_write8(a+2,(d>>8) &0xff, 32);\r
// This is part of Pico Library
// (c) Copyright 2004 Dave, All rights reserved.
-// (c) Copyright 2006 notaz, All rights reserved.
+// (c) Copyright 2007 notaz, All rights reserved.
// Free for non-commercial use.
// For commercial use, separate licencing terms must be obtained.
#include "../sound/sound.h"
-int counter75hz = 0;
+static int counter75hz = 0; // TODO: move 2 context
int PicoInitMCD(void)
// clear everything except BIOS
memset(Pico_mcd->prg_ram, 0, sizeof(mcd_state) - sizeof(Pico_mcd->bios));
PicoMCD |= 2; // s68k reset pending
+ Pico_mcd->s68k_regs[3] = 1; // 2M word RAM mode with m68k access after reset
counter75hz = 0;
LC89510_Reset();
static int PicoFrameHintsMCD(void)
{
struct PicoVideo *pv=&Pico.video;
- int total_z80=0,lines,y,lines_vis = 224,z80CycleAim = 0,line_sample;
+ int total_z80=0,lines,y,lines_vis = 224,z80CycleAim = 0,line_sample,counter75hz_lim;
const int cycles_68k=488,cycles_z80=228,cycles_s68k=795; // both PAL and NTSC compile to same values
int skip=PicoSkipFrame || (PicoOpt&0x10);
int hint; // Hint counter
//cycles_z80 = (int) ((double) OSC_PAL / 15 / 50 / 312 + 0.4); // 228
lines = 312; // Steve Snake says there are 313 lines, but this seems to also work well
line_sample = 68;
+ counter75hz_lim = 2080;
if(pv->reg[1]&8) lines_vis = 240;
} else {
//cycles_68k = (int) ((double) OSC_NTSC / 7 / 60 / 262 + 0.4); // 488
//cycles_z80 = (int) ((double) OSC_NTSC / 15 / 60 / 262 + 0.4); // 228
lines = 262;
+ counter75hz_lim = 2096;
line_sample = 93;
}
// Run scanline:
//dprintf("m68k starting exec @ %06x", SekPc);
+ if(Pico.m.dma_bytes) SekCycleCnt+=CheckDMA();
SekRun(cycles_68k);
if ((Pico_mcd->m68k_regs[1]&3) == 1) { // no busreq/no reset
#if 0
total_z80+=z80_run(z80CycleAim-total_z80);
}
- // if cdd is on, counter elapsed and irq4 is not masked, do irq4
- if ((Pico_mcd->s68k_regs[0x37]&4) && ++counter75hz > 209 && (Pico_mcd->s68k_regs[0x33]&(1<<4))) {
- counter75hz = 0;
+ if ((counter75hz+=10) >= counter75hz_lim) {
+ counter75hz -= counter75hz_lim;
Check_CD_Command();
}
}