runs code in 1M wram, cell arrange, decode (untested)

git-svn-id: file:///home/notaz/opt/svn/PicoDrive@54 be3aeb3a-fb24-0410-a615-afba39da0efa
This commit is contained in:
notaz 2007-02-21 22:23:37 +00:00
parent 3a81ecde1c
commit fa1e5e2948
16 changed files with 787 additions and 551 deletions

View file

@ -107,71 +107,12 @@ static int SRAMRead(u32 a)
} }
#endif #endif
static int PadRead(int i)
{
int pad=0,value=0,TH;
pad=~PicoPad[i]; // Get inverse of pad MXYZ SACB RLDU
TH=Pico.ioports[i+1]&0x40;
if(PicoOpt & 0x20) { // 6 button gamepad enabled
int phase = Pico.m.padTHPhase[i];
if(phase == 2 && !TH) {
value=(pad&0xc0)>>2; // ?0SA 0000
goto end;
} else if(phase == 3 && TH) {
value=(pad&0x30)|((pad>>8)&0xf); // ?1CB MXYZ
goto end;
} else if(phase == 3 && !TH) {
value=((pad&0xc0)>>2)|0x0f; // ?0SA 1111
goto end;
}
}
if(TH) value=(pad&0x3f); // ?1CB RLDU
else value=((pad&0xc0)>>2)|(pad&3); // ?0SA 00DU
end:
// orr the bits, which are set as output
value |= Pico.ioports[i+1]&Pico.ioports[i+4];
return value; // will mirror later
}
u8 z80Read8(u32 a)
{
if(Pico.m.z80Run&1) return 0;
a&=0x1fff;
if(!(PicoOpt&4)) {
// Z80 disabled, do some faking
static u8 zerosent = 0;
if(a == Pico.m.z80_lastaddr) { // probably polling something
u8 d = Pico.m.z80_fakeval;
if((d & 0xf) == 0xf && !zerosent) {
d = 0; zerosent = 1;
} else {
Pico.m.z80_fakeval++;
zerosent = 0;
}
return d;
} else {
Pico.m.z80_fakeval = 0;
}
}
Pico.m.z80_lastaddr = (u16) a;
return Pico.zram[a];
}
// for nonstandard reads // for nonstandard reads
#ifndef _ASM_MEMORY_C #ifndef _ASM_MEMORY_C
static static
#endif #endif
u32 UnusualRead16(u32 a, int realsize) u32 OtherRead16End(u32 a, int realsize)
{ {
u32 d=0; u32 d=0;
@ -242,109 +183,11 @@ end:
return d; return d;
} }
#ifndef _ASM_MEMORY_C
static
#endif
u32 OtherRead16(u32 a, int realsize)
{
u32 d=0;
if ((a&0xff0000)==0xa00000) {
if ((a&0x4000)==0x0000) { d=z80Read8(a); d|=d<<8; goto end; } // Z80 ram (not byteswaped)
if ((a&0x6000)==0x4000) { if(PicoOpt&1) d=YM2612Read(); else d=Pico.m.rotate++&3; dprintf("read ym2612: %04x", d); goto end; } // 0x4000-0x5fff, Fudge if disabled
d=0xffff; goto end;
}
if ((a&0xffffe0)==0xa10000) { // I/O ports
a=(a>>1)&0xf;
switch(a) {
case 0: d=Pico.m.hardware; break; // Hardware value (Version register)
case 1: d=PadRead(0); d|=Pico.ioports[1]&0x80; break;
case 2: d=PadRead(1); d|=Pico.ioports[2]&0x80; break;
default: d=Pico.ioports[a]; break; // IO ports can be used as RAM
}
d|=d<<8;
goto end;
}
// |=0x80 for Shadow of the Beast & Super Offroad; rotate fakes next fetched instruction for Time Killers
if (a==0xa11100) {
d=Pico.m.z80Run&1;
#if 0
if (!d) {
// do we need this?
extern int z80stopCycle; // TODO: tidy
int stop_before = SekCyclesDone() - z80stopCycle;
if (stop_before > 0 && stop_before <= 16) // Gens uses 16 here
d = 1; // bus not yet available
}
#endif
d=(d<<8)|0x8000|Pico.m.rotate++;
dprintf("get_zrun: %04x [%i|%i] @%06x", d, Pico.m.scanline, SekCyclesDone(), SekPc);
goto end; }
#ifndef _ASM_MEMORY_C
if ((a&0xe700e0)==0xc00000) { d=PicoVideoRead(a); goto end; }
#endif
d = UnusualRead16(a, realsize);
end:
return d;
}
//extern UINT32 mz80GetRegisterValue(void *, UINT32); //extern UINT32 mz80GetRegisterValue(void *, UINT32);
static void OtherWrite8(u32 a,u32 d,int realsize) static void OtherWrite8End(u32 a,u32 d,int realsize)
{ {
if ((a&0xe700f9)==0xc00011||(a&0xff7ff9)==0xa07f11) { if(PicoOpt&2) SN76496Write(d); return; } // PSG Sound
if ((a&0xff4000)==0xa00000) { if(!(Pico.m.z80Run&1)) Pico.zram[a&0x1fff]=(u8)d; return; } // Z80 ram
if ((a&0xff6000)==0xa04000) { if(PicoOpt&1) emustatus|=YM2612Write(a&3, d); return; } // FM Sound
if ((a&0xffffe0)==0xa10000) { // I/O ports
a=(a>>1)&0xf;
// 6 button gamepad: if TH went from 0 to 1, gamepad changes state
if(PicoOpt&0x20) {
if(a==1) {
Pico.m.padDelay[0] = 0;
if(!(Pico.ioports[1]&0x40) && (d&0x40)) Pico.m.padTHPhase[0]++;
}
else if(a==2) {
Pico.m.padDelay[1] = 0;
if(!(Pico.ioports[2]&0x40) && (d&0x40)) Pico.m.padTHPhase[1]++;
}
}
Pico.ioports[a]=(u8)d; // IO ports can be used as RAM
return;
}
if (a==0xa11100) {
extern int z80startCycle, z80stopCycle;
//int lineCycles=(488-SekCyclesLeft)&0x1ff;
d&=1; d^=1;
if(!d) {
// this is for a nasty situation where Z80 was enabled and disabled in the same 68k timeslice (Golden Axe III)
if (Pico.m.z80Run) {
int lineCycles=(488-SekCyclesLeft)&0x1ff;
z80stopCycle = SekCyclesDone();
lineCycles=(lineCycles>>1)-(lineCycles>>5);
z80_run(lineCycles);
}
} else {
z80startCycle = SekCyclesDone();
//if(Pico.m.scanline != -1)
}
dprintf("set_zrun: %02x [%i|%i] @%06x", d, Pico.m.scanline, SekCyclesDone(), /*mz80GetRegisterValue(NULL, 0),*/ SekPc);
Pico.m.z80Run=(u8)d; return;
}
if (a==0xa11200) { dprintf("write z80Reset: %02x", d); if(!(d&1)) z80_reset(); return; }
if ((a&0xff7f00)==0xa06000) // Z80 BANK register
{
Pico.m.z80_bank68k>>=1;
Pico.m.z80_bank68k|=(d&1)<<8;
Pico.m.z80_bank68k&=0x1ff; // 9 bits and filled in the new top one
return;
}
if ((a&0xe700e0)==0xc00000) { PicoVideoWrite(a,(u16)(d|(d<<8))); return; } // Byte access gets mirrored
// sram // sram
//if(a==0x200000) dprintf("cc : %02x @ %06x [%i|%i]", d, SekPc, SekCyclesDoneT(), SekCyclesDone()); //if(a==0x200000) dprintf("cc : %02x @ %06x [%i|%i]", d, SekPc, SekCyclesDoneT(), SekCyclesDone());
//if(a==0x200001) dprintf("w8 : %02x @ %06x [%i]", d, SekPc, SekCyclesDoneT()); //if(a==0x200001) dprintf("w8 : %02x @ %06x [%i]", d, SekPc, SekCyclesDoneT());
@ -408,33 +251,9 @@ static void OtherWrite8(u32 a,u32 d,int realsize)
Pico.m.prot_bytes[(a>>2)&1] = (u8)d; Pico.m.prot_bytes[(a>>2)&1] = (u8)d;
} }
static void OtherWrite16(u32 a,u32 d)
{
if ((a&0xe700e0)==0xc00000) { PicoVideoWrite(a,(u16)d); return; }
if ((a&0xff4000)==0xa00000) { if(!(Pico.m.z80Run&1)) Pico.zram[a&0x1fff]=(u8)(d>>8); return; } // Z80 ram (MSB only)
if ((a&0xffffe0)==0xa10000) { // I/O ports #include "MemoryCmn.c"
a=(a>>1)&0xf;
// 6 button gamepad: if TH went from 0 to 1, gamepad changes state
if(PicoOpt&0x20) {
if(a==1) {
Pico.m.padDelay[0] = 0;
if(!(Pico.ioports[1]&0x40) && (d&0x40)) Pico.m.padTHPhase[0]++;
}
else if(a==2) {
Pico.m.padDelay[1] = 0;
if(!(Pico.ioports[2]&0x40) && (d&0x40)) Pico.m.padTHPhase[1]++;
}
}
Pico.ioports[a]=(u8)d; // IO ports can be used as RAM
return;
}
if (a==0xa11100) { OtherWrite8(a, d>>8, 16); return; }
if (a==0xa11200) { dprintf("write z80reset: %04x", d); if(!(d&0x100)) z80_reset(); return; }
OtherWrite8(a, d>>8, 16);
OtherWrite8(a+1,d&0xff, 16);
}
// ----------------------------------------------------------------- // -----------------------------------------------------------------
// Read Rom and read Ram // Read Rom and read Ram

219
Pico/MemoryCmn.c Normal file
View file

@ -0,0 +1,219 @@
/* common code for Memory.c and cd/Memory.c */
static int PadRead(int i)
{
int pad=0,value=0,TH;
pad=~PicoPad[i]; // Get inverse of pad MXYZ SACB RLDU
TH=Pico.ioports[i+1]&0x40;
if(PicoOpt & 0x20) { // 6 button gamepad enabled
int phase = Pico.m.padTHPhase[i];
if(phase == 2 && !TH) {
value=(pad&0xc0)>>2; // ?0SA 0000
goto end;
} else if(phase == 3 && TH) {
value=(pad&0x30)|((pad>>8)&0xf); // ?1CB MXYZ
goto end;
} else if(phase == 3 && !TH) {
value=((pad&0xc0)>>2)|0x0f; // ?0SA 1111
goto end;
}
}
if(TH) value=(pad&0x3f); // ?1CB RLDU
else value=((pad&0xc0)>>2)|(pad&3); // ?0SA 00DU
end:
// orr the bits, which are set as output
value |= Pico.ioports[i+1]&Pico.ioports[i+4];
return value; // will mirror later
}
#ifndef _ASM_MEMORY_C
static
#endif
u8 z80Read8(u32 a)
{
if(Pico.m.z80Run&1) return 0;
a&=0x1fff;
if(!(PicoOpt&4)) {
// Z80 disabled, do some faking
static u8 zerosent = 0;
if(a == Pico.m.z80_lastaddr) { // probably polling something
u8 d = Pico.m.z80_fakeval;
if((d & 0xf) == 0xf && !zerosent) {
d = 0; zerosent = 1;
} else {
Pico.m.z80_fakeval++;
zerosent = 0;
}
return d;
} else {
Pico.m.z80_fakeval = 0;
}
}
Pico.m.z80_lastaddr = (u16) a;
return Pico.zram[a];
}
#ifndef _ASM_MEMORY_C
static
#endif
u32 OtherRead16(u32 a, int realsize)
{
u32 d=0;
if ((a&0xff0000)==0xa00000) {
if ((a&0x4000)==0x0000) { d=z80Read8(a); d|=d<<8; goto end; } // Z80 ram (not byteswaped)
if ((a&0x6000)==0x4000) { // 0x4000-0x5fff, Fudge if disabled
if(PicoOpt&1) d=YM2612Read();
else d=Pico.m.rotate++&3;
dprintf("read ym2612: %04x", d);
goto end;
}
d=0xffff;
goto end;
}
if ((a&0xffffe0)==0xa10000) { // I/O ports
a=(a>>1)&0xf;
switch(a) {
case 0: d=Pico.m.hardware; break; // Hardware value (Version register)
case 1: d=PadRead(0); d|=Pico.ioports[1]&0x80; break;
case 2: d=PadRead(1); d|=Pico.ioports[2]&0x80; break;
default: d=Pico.ioports[a]; break; // IO ports can be used as RAM
}
d|=d<<8;
goto end;
}
// |=0x80 for Shadow of the Beast & Super Offroad; rotate fakes next fetched instruction for Time Killers
if (a==0xa11100) { // z80 busreq
d=Pico.m.z80Run&1;
#if 0
if (!d) {
// do we need this?
extern int z80stopCycle;
int stop_before = SekCyclesDone() - z80stopCycle;
if (stop_before > 0 && stop_before <= 16) // Gens uses 16 here
d = 1; // bus not yet available
}
#endif
d=(d<<8)|0x8000|Pico.m.rotate++;
dprintf("get_zrun: %04x [%i|%i] @%06x", d, Pico.m.scanline, SekCyclesDone(), SekPc);
goto end;
}
#ifndef _ASM_MEMORY_C
if ((a&0xe700e0)==0xc00000) { d=PicoVideoRead(a); goto end; }
#endif
d = OtherRead16End(a, realsize);
end:
return d;
}
//extern UINT32 mz80GetRegisterValue(void *, UINT32);
static void OtherWrite8(u32 a,u32 d,int realsize)
{
if ((a&0xe700f9)==0xc00011||(a&0xff7ff9)==0xa07f11) { if(PicoOpt&2) SN76496Write(d); return; } // PSG Sound
if ((a&0xff4000)==0xa00000) { if(!(Pico.m.z80Run&1)) Pico.zram[a&0x1fff]=(u8)d; return; } // Z80 ram
if ((a&0xff6000)==0xa04000) { if(PicoOpt&1) emustatus|=YM2612Write(a&3, d); return; } // FM Sound
if ((a&0xffffe0)==0xa10000) { // I/O ports
a=(a>>1)&0xf;
// 6 button gamepad: if TH went from 0 to 1, gamepad changes state
if(PicoOpt&0x20) {
if(a==1) {
Pico.m.padDelay[0] = 0;
if(!(Pico.ioports[1]&0x40) && (d&0x40)) Pico.m.padTHPhase[0]++;
}
else if(a==2) {
Pico.m.padDelay[1] = 0;
if(!(Pico.ioports[2]&0x40) && (d&0x40)) Pico.m.padTHPhase[1]++;
}
}
Pico.ioports[a]=(u8)d; // IO ports can be used as RAM
return;
}
if (a==0xa11100) {
extern int z80startCycle, z80stopCycle;
//int lineCycles=(488-SekCyclesLeft)&0x1ff;
d&=1; d^=1;
if(!d) {
// this is for a nasty situation where Z80 was enabled and disabled in the same 68k timeslice (Golden Axe III)
if (Pico.m.z80Run) {
int lineCycles=(488-SekCyclesLeft)&0x1ff;
z80stopCycle = SekCyclesDone();
lineCycles=(lineCycles>>1)-(lineCycles>>5);
z80_run(lineCycles);
}
} else {
z80startCycle = SekCyclesDone();
//if(Pico.m.scanline != -1)
}
dprintf("set_zrun: %02x [%i|%i] @%06x", d, Pico.m.scanline, SekCyclesDone(), /*mz80GetRegisterValue(NULL, 0),*/ SekPc);
Pico.m.z80Run=(u8)d; return;
}
if (a==0xa11200) {
dprintf("write z80Reset: %02x", d);
if(!(d&1)) z80_reset();
return;
}
if ((a&0xff7f00)==0xa06000) // Z80 BANK register
{
Pico.m.z80_bank68k>>=1;
Pico.m.z80_bank68k|=(d&1)<<8;
Pico.m.z80_bank68k&=0x1ff; // 9 bits and filled in the new top one
return;
}
if ((a&0xe700e0)==0xc00000) {
PicoVideoWrite(a,(u16)(d|(d<<8))); // Byte access gets mirrored
return;
}
OtherWrite8End(a, d, realsize);
}
static void OtherWrite16(u32 a,u32 d)
{
if ((a&0xe700e0)==0xc00000) { PicoVideoWrite(a,(u16)d); return; }
if ((a&0xff4000)==0xa00000) { if(!(Pico.m.z80Run&1)) Pico.zram[a&0x1fff]=(u8)(d>>8); return; } // Z80 ram (MSB only)
if ((a&0xffffe0)==0xa10000) { // I/O ports
a=(a>>1)&0xf;
// 6 button gamepad: if TH went from 0 to 1, gamepad changes state
if(PicoOpt&0x20) {
if(a==1) {
Pico.m.padDelay[0] = 0;
if(!(Pico.ioports[1]&0x40) && (d&0x40)) Pico.m.padTHPhase[0]++;
}
else if(a==2) {
Pico.m.padDelay[1] = 0;
if(!(Pico.ioports[2]&0x40) && (d&0x40)) Pico.m.padTHPhase[1]++;
}
}
Pico.ioports[a]=(u8)d; // IO ports can be used as RAM
return;
}
if (a==0xa11100) { OtherWrite8(a, d>>8, 16); return; }
if (a==0xa11200) { dprintf("write z80reset: %04x", d); if(!(d&0x100)) z80_reset(); return; }
OtherWrite8(a, d>>8, 16);
OtherWrite8(a+1,d&0xff, 16);
}

View file

@ -198,13 +198,22 @@ struct mcd_misc
typedef struct typedef struct
{ {
unsigned char bios[0x20000]; // 128K unsigned char bios[0x20000]; // 128K
union { union { // 512K
unsigned char prg_ram[0x80000]; // 512K unsigned char prg_ram[0x80000];
unsigned char prg_ram_b[4][0x20000]; unsigned char prg_ram_b[4][0x20000];
}; };
unsigned char word_ram[0x40000]; // 256K union { // 256K
union { struct {
unsigned char pcm_ram[0x10000]; // 64K unsigned char word_ram2M[0x40000];
unsigned char unused[0x20000];
};
struct {
unsigned char unused[0x20000];
unsigned char word_ram1M[2][0x20000];
};
};
union { // 64K
unsigned char pcm_ram[0x10000];
unsigned char pcm_ram_b[0x10][0x1000]; unsigned char pcm_ram_b[0x10][0x1000];
}; };
unsigned char bram[0x2000]; // 8K unsigned char bram[0x2000]; // 8K
@ -293,6 +302,10 @@ void memcpy16(unsigned short *dest, unsigned short *src, int count);
void memcpy32(int *dest, int *src, int count); void memcpy32(int *dest, int *src, int count);
void memset32(int *dest, int c, int count); void memset32(int *dest, int c, int count);
// cd/Misc.c
void wram_2M_to_1M(unsigned char *m);
void wram_1M_to_2M(unsigned char *m);
#ifdef __cplusplus #ifdef __cplusplus
} // End of extern "C" } // End of extern "C"

View file

@ -8,6 +8,7 @@
#include "PicoInt.h" #include "PicoInt.h"
#include "cd/gfx_cd.h"
extern const unsigned char hcounts_32[]; extern const unsigned char hcounts_32[];
extern const unsigned char hcounts_40[]; extern const unsigned char hcounts_40[];
@ -98,25 +99,31 @@ static void DmaSlow(int len)
pd=(u16 *)(Pico.ram+(source&0xfffe)); pd=(u16 *)(Pico.ram+(source&0xfffe));
pdend=(u16 *)(Pico.ram+0x10000); pdend=(u16 *)(Pico.ram+0x10000);
} else if(PicoMCD & 1) { } else if(PicoMCD & 1) {
dprintf("DmaSlow CD"); dprintf("DmaSlow CD, r3=%02x", Pico_mcd->s68k_regs[3]);
if(source<0x20000) { // Bios area if(source<0x20000) { // Bios area
pd=(u16 *)(Pico_mcd->bios+(source&~1)); pd=(u16 *)(Pico_mcd->bios+(source&~1));
pdend=(u16 *)(Pico_mcd->bios+0x20000); pdend=(u16 *)(Pico_mcd->bios+0x20000);
} else if ((source&0xfc0000)==0x200000 && (!(Pico_mcd->s68k_regs[3]&4))) { // Word Ram } else if ((source&0xfc0000)==0x200000) { // Word Ram
source -= 2;
if (!(Pico_mcd->s68k_regs[3]&4)) { // 2M mode if (!(Pico_mcd->s68k_regs[3]&4)) { // 2M mode
source -= 2; pd=(u16 *)(Pico_mcd->word_ram2M+(source&0x3fffe));
pd=(u16 *)(Pico_mcd->word_ram+(source&0x3fffe)); pdend=(u16 *)(Pico_mcd->word_ram2M+0x40000);
pdend=(u16 *)(Pico_mcd->word_ram+0x40000);
} else { } else {
dprintf("DmaSlow: unsupported src"); if (source < 0x220000) { // 1M mode
return; int bank = Pico_mcd->s68k_regs[3]&1;
pd=(u16 *)(Pico_mcd->word_ram1M[bank]+(source&0x1fffe));
pdend=(u16 *)(Pico_mcd->word_ram1M[bank]+0x20000);
} else {
DmaSlowCell(source, a, len, inc);
return;
}
} }
} else if ((source&0xfe0000)==0x020000) { // Prg Ram } else if ((source&0xfe0000)==0x020000) { // Prg Ram
u8 *prg_ram = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6]; u8 *prg_ram = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6];
pd=(u16 *)(prg_ram+(source&0x1fffe)); pd=(u16 *)(prg_ram+(source&0x1fffe));
pdend=(u16 *)(prg_ram+0x20000); pdend=(u16 *)(prg_ram+0x20000);
} else { } else {
dprintf("DmaSlow: unsupported src"); dprintf("DmaSlow FIXME: unsupported src");
return; return;
} }
} else { } else {
@ -142,8 +149,8 @@ static void DmaSlow(int len)
if (inc == 2 && !(a&1) && a+len*2 < 0x10000) if (inc == 2 && !(a&1) && a+len*2 < 0x10000)
{ {
// most used DMA mode // most used DMA mode
memcpy16(r + (a>>1), pd, len); memcpy16(r + (a>>1), pd, len);
a += len*2; a += len*2;
} }
else else
{ {

View file

@ -125,10 +125,13 @@ int PicoCdSaveState(void *file)
Pico_mcd->m.audio_offset = mp3_get_offset(); Pico_mcd->m.audio_offset = mp3_get_offset();
memset(buff, 0, sizeof(buff)); memset(buff, 0, sizeof(buff));
PicoAreaPackCpu(buff, 1); PicoAreaPackCpu(buff, 1);
if (Pico_mcd->s68k_regs[3]&4) // 1M mode?
wram_1M_to_2M(Pico_mcd->word_ram2M);
Pico_mcd->m.hint_vector = *(unsigned short *)(Pico_mcd->bios + 0x72);
CHECKED_WRITE_BUFF(CHUNK_S68K, buff); CHECKED_WRITE_BUFF(CHUNK_S68K, buff);
CHECKED_WRITE_BUFF(CHUNK_PRG_RAM, Pico_mcd->prg_ram); CHECKED_WRITE_BUFF(CHUNK_PRG_RAM, Pico_mcd->prg_ram);
CHECKED_WRITE_BUFF(CHUNK_WORD_RAM, Pico_mcd->word_ram); // in 2M format CHECKED_WRITE_BUFF(CHUNK_WORD_RAM, Pico_mcd->word_ram2M); // in 2M format
CHECKED_WRITE_BUFF(CHUNK_PCM_RAM, Pico_mcd->pcm_ram); CHECKED_WRITE_BUFF(CHUNK_PCM_RAM, Pico_mcd->pcm_ram);
CHECKED_WRITE_BUFF(CHUNK_BRAM, Pico_mcd->bram); CHECKED_WRITE_BUFF(CHUNK_BRAM, Pico_mcd->bram);
CHECKED_WRITE_BUFF(CHUNK_GA_REGS, Pico_mcd->s68k_regs); // GA regs, not CPU regs CHECKED_WRITE_BUFF(CHUNK_GA_REGS, Pico_mcd->s68k_regs); // GA regs, not CPU regs
@ -138,6 +141,9 @@ int PicoCdSaveState(void *file)
CHECKED_WRITE_BUFF(CHUNK_SCD, Pico_mcd->scd); CHECKED_WRITE_BUFF(CHUNK_SCD, Pico_mcd->scd);
CHECKED_WRITE_BUFF(CHUNK_RC, Pico_mcd->rot_comp); CHECKED_WRITE_BUFF(CHUNK_RC, Pico_mcd->rot_comp);
CHECKED_WRITE_BUFF(CHUNK_MISC_CD, Pico_mcd->m); CHECKED_WRITE_BUFF(CHUNK_MISC_CD, Pico_mcd->m);
if (Pico_mcd->s68k_regs[3]&4) // convert back
wram_2M_to_1M(Pico_mcd->word_ram2M);
} }
return 0; return 0;
@ -216,7 +222,7 @@ int PicoCdLoadState(void *file)
break; break;
case CHUNK_PRG_RAM: CHECKED_READ_BUFF(Pico_mcd->prg_ram); break; case CHUNK_PRG_RAM: CHECKED_READ_BUFF(Pico_mcd->prg_ram); break;
case CHUNK_WORD_RAM: CHECKED_READ_BUFF(Pico_mcd->word_ram); break; case CHUNK_WORD_RAM: CHECKED_READ_BUFF(Pico_mcd->word_ram2M); break;
case CHUNK_PCM_RAM: CHECKED_READ_BUFF(Pico_mcd->pcm_ram); break; case CHUNK_PCM_RAM: CHECKED_READ_BUFF(Pico_mcd->pcm_ram); break;
case CHUNK_BRAM: CHECKED_READ_BUFF(Pico_mcd->bram); break; case CHUNK_BRAM: CHECKED_READ_BUFF(Pico_mcd->bram); break;
case CHUNK_GA_REGS: CHECKED_READ_BUFF(Pico_mcd->s68k_regs); break; case CHUNK_GA_REGS: CHECKED_READ_BUFF(Pico_mcd->s68k_regs); break;
@ -225,19 +231,22 @@ int PicoCdLoadState(void *file)
case CHUNK_CDC: CHECKED_READ_BUFF(Pico_mcd->cdc); break; case CHUNK_CDC: CHECKED_READ_BUFF(Pico_mcd->cdc); break;
case CHUNK_SCD: CHECKED_READ_BUFF(Pico_mcd->scd); break; case CHUNK_SCD: CHECKED_READ_BUFF(Pico_mcd->scd); break;
case CHUNK_RC: CHECKED_READ_BUFF(Pico_mcd->rot_comp); break; case CHUNK_RC: CHECKED_READ_BUFF(Pico_mcd->rot_comp); break;
case CHUNK_MISC_CD: CHECKED_READ_BUFF(Pico_mcd->m); break;
case CHUNK_MISC_CD:
CHECKED_READ_BUFF(Pico_mcd->m);
mp3_start_play(Pico_mcd->TOC.Tracks[Pico_mcd->m.audio_track].F, Pico_mcd->m.audio_offset);
break;
default: default:
printf("skipping unknown chunk %i of size %i\n", buff[0], len); printf("PicoCdLoadState: skipping unknown chunk %i of size %i\n", buff[0], len);
areaSeek(file, len, SEEK_CUR); areaSeek(file, len, SEEK_CUR);
break; break;
} }
} }
/* after load events */
if (Pico_mcd->s68k_regs[3]&4) // 1M mode?
wram_2M_to_1M(Pico_mcd->word_ram2M);
mp3_start_play(Pico_mcd->TOC.Tracks[Pico_mcd->m.audio_track].F, Pico_mcd->m.audio_offset);
// restore hint vector
*(unsigned short *)(Pico_mcd->bios + 0x72) = Pico_mcd->m.hint_vector;
return 0; return 0;
} }

View file

@ -104,19 +104,20 @@ void Update_CDC_TRansfer(int which)
{ {
if (Pico_mcd->s68k_regs[3] & 4) if (Pico_mcd->s68k_regs[3] & 4)
{ {
// test: Final Fight
int bank = !(Pico_mcd->s68k_regs[3]&1);
dep = ((DMA_Adr & 0x3FFF) << 3); dep = ((DMA_Adr & 0x3FFF) << 3);
cdprintf("CD DMA # %04x -> word_ram1M # %06x, len=%i", cdprintf("CD DMA # %04x -> word_ram1M # %06x, len=%i",
Pico_mcd->cdc.DAC.N, dep, length); Pico_mcd->cdc.DAC.N, dep, length);
dep = ((DMA_Adr & 0x3FFF) << 4); dest = (unsigned short *) (Pico_mcd->word_ram1M[bank] + dep);
if (!(Pico_mcd->s68k_regs[3]&1)) dep += 2;
dest = (unsigned short *) (Pico_mcd->word_ram + dep);
for (len = length; len > 0; len--, src+=2, dest+=2) // TODO: bswapcpy
for (len = length; len > 0; len--, src+=2, dest++)
*dest = (src[0]<<8) | src[1]; *dest = (src[0]<<8) | src[1];
{ // debug { // debug
unsigned char *b1 = Pico_mcd->word_ram + dep; unsigned char *b1 = Pico_mcd->word_ram1M[bank] + dep;
unsigned char *b2 = (unsigned char *)dest - 8; unsigned char *b2 = (unsigned char *)dest - 8;
dprintf("%02x %02x %02x %02x .. %02x %02x %02x %02x", dprintf("%02x %02x %02x %02x .. %02x %02x %02x %02x",
b1[0], b1[1], b1[4], b1[5], b2[0], b2[1], b2[4], b2[5]); b1[0], b1[1], b1[4], b1[5], b2[0], b2[1], b2[4], b2[5]);
@ -127,13 +128,13 @@ void Update_CDC_TRansfer(int which)
dep = ((DMA_Adr & 0x7FFF) << 3); dep = ((DMA_Adr & 0x7FFF) << 3);
cdprintf("CD DMA # %04x -> word_ram2M # %06x, len=%i", cdprintf("CD DMA # %04x -> word_ram2M # %06x, len=%i",
Pico_mcd->cdc.DAC.N, dep, length); Pico_mcd->cdc.DAC.N, dep, length);
dest = (unsigned short *) (Pico_mcd->word_ram + dep); dest = (unsigned short *) (Pico_mcd->word_ram2M + dep);
for (len = length; len > 0; len--, src+=2, dest++) for (len = length; len > 0; len--, src+=2, dest++)
*dest = (src[0]<<8) | src[1]; *dest = (src[0]<<8) | src[1];
{ // debug { // debug
unsigned char *b1 = Pico_mcd->word_ram + dep; unsigned char *b1 = Pico_mcd->word_ram2M + dep;
unsigned char *b2 = (unsigned char *)dest - 4; unsigned char *b2 = (unsigned char *)dest - 4;
dprintf("%02x %02x %02x %02x .. %02x %02x %02x %02x", dprintf("%02x %02x %02x %02x .. %02x %02x %02x %02x",
b1[0], b1[1], b1[2], b1[3], b2[0], b2[1], b2[2], b2[3]); b1[0], b1[1], b1[2], b1[3], b2[0], b2[1], b2[2], b2[3]);
@ -146,7 +147,7 @@ void Update_CDC_TRansfer(int which)
dest = (unsigned char *) Ram_PCM; dest = (unsigned char *) Ram_PCM;
dep = ((DMA_Adr & 0x03FF) << 2) + PCM_Chip.Bank; dep = ((DMA_Adr & 0x03FF) << 2) + PCM_Chip.Bank;
#else #else
cdprintf("CD DMA # %04x -> PCM TODO", Pico_mcd->cdc.DAC.N); dprintf("FIXME: CD DMA # %04x -> PCM", Pico_mcd->cdc.DAC.N);
#endif #endif
} }
else if (which == 5) // PRG RAM else if (which == 5) // PRG RAM
@ -188,7 +189,7 @@ unsigned short Read_CDC_Host(int is_sub)
if (!(Pico_mcd->scd.Status_CDC & 0x08)) if (!(Pico_mcd->scd.Status_CDC & 0x08))
{ {
// Transfer data disabled // Transfer data disabled
cdprintf("Read_CDC_Host: Transfer data disabled"); cdprintf("Read_CDC_Host FIXME: Transfer data disabled");
return 0; return 0;
} }
@ -196,7 +197,7 @@ unsigned short Read_CDC_Host(int is_sub)
(!is_sub && (Pico_mcd->s68k_regs[4] & 7) != 2)) (!is_sub && (Pico_mcd->s68k_regs[4] & 7) != 2))
{ {
// Wrong setting // Wrong setting
cdprintf("Read_CDC_Host: Wrong setting"); cdprintf("Read_CDC_Host FIXME: Wrong setting");
return 0; return 0;
} }

View file

@ -19,6 +19,8 @@
#include "gfx_cd.h" #include "gfx_cd.h"
#include "pcm.h" #include "pcm.h"
#include "cell_map.c"
typedef unsigned char u8; typedef unsigned char u8;
typedef unsigned short u16; typedef unsigned short u16;
typedef unsigned int u32; typedef unsigned int u32;
@ -55,7 +57,7 @@ static u32 m68k_reg_read16(u32 a)
d = Read_CDC_Host(0); d = Read_CDC_Host(0);
goto end; goto end;
case 0xA: case 0xA:
dprintf("m68k reserved read"); dprintf("m68k FIXME: reserved read");
goto end; goto end;
case 0xC: case 0xC:
dprintf("m68k stopwatch timer read"); dprintf("m68k stopwatch timer read");
@ -69,7 +71,7 @@ static u32 m68k_reg_read16(u32 a)
goto end; goto end;
} }
dprintf("m68k_regs invalid read @ %02x", a); dprintf("m68k_regs FIXME invalid read @ %02x", a);
end: end:
@ -115,12 +117,13 @@ static void m68k_reg_write8(u32 a, u32 d)
Pico_mcd->s68k_regs[3] = d; // really use s68k side register Pico_mcd->s68k_regs[3] = d; // really use s68k side register
return; return;
case 6: case 6:
*((char *)&Pico_mcd->m.hint_vector+1) = d; dprintf("FIXME hint[2]: %02x @%06x", (u8)d, SekPc);
Pico_mcd->bios[0x72 + 1] = d; // simple hint vector changer Pico_mcd->bios[0x72 + 1] = d; // simple hint vector changer
return; return;
case 7: case 7:
*(char *)&Pico_mcd->m.hint_vector = d; dprintf("FIXME hint[3]: %02x @%06x", (u8)d, SekPc);
Pico_mcd->bios[0x72] = d; Pico_mcd->bios[0x72] = d;
dprintf("vector is now %08x", PicoRead32(0x70));
return; return;
case 0xe: case 0xe:
//dprintf("m68k: comm flag: %02x", d); //dprintf("m68k: comm flag: %02x", d);
@ -133,7 +136,7 @@ static void m68k_reg_write8(u32 a, u32 d)
return; return;
} }
dprintf("m68k: invalid write? [%02x] %02x", a, d); dprintf("m68k FIXME: invalid write? [%02x] %02x", a, d);
} }
@ -187,17 +190,27 @@ static void s68k_reg_write8(u32 a, u32 d)
switch (a) { switch (a) {
case 2: case 2:
return; // only m68k can change WP return; // only m68k can change WP
case 3: case 3: {
int dold = Pico_mcd->s68k_regs[3];
dprintf("s68k_regs w3: %02x @%06x", (u8)d, SekPc); dprintf("s68k_regs w3: %02x @%06x", (u8)d, SekPc);
d &= 0x1d; d &= 0x1d;
if (d&4) { if (d&4) {
d |= Pico_mcd->s68k_regs[3]&0xc2; d |= dold&0xc2;
if ((d ^ Pico_mcd->s68k_regs[3]) & 5) d &= ~2; // in case of mode or bank change we clear DMNA (m68k req) bit if ((d ^ dold) & 5) d &= ~2; // in case of mode or bank change we clear DMNA (m68k req) bit
if (!(dold & 4)) {
dprintf("wram mode 2M->1M");
wram_2M_to_1M(Pico_mcd->word_ram2M);
}
} else { } else {
d |= Pico_mcd->s68k_regs[3]&0xc3; d |= Pico_mcd->s68k_regs[3]&0xc3;
if (d&1) d &= ~2; // return word RAM to m68k in 2M mode if (d&1) d &= ~2; // return word RAM to m68k in 2M mode
if (dold & 4) {
dprintf("wram mode 1M->2M");
wram_1M_to_2M(Pico_mcd->word_ram2M);
}
} }
break; break;
}
case 4: case 4:
dprintf("s68k CDC dest: %x", d&7); dprintf("s68k CDC dest: %x", d&7);
Pico_mcd->s68k_regs[4] = (Pico_mcd->s68k_regs[4]&0xC0) | (d&7); // CDC mode Pico_mcd->s68k_regs[4] = (Pico_mcd->s68k_regs[4]&0xC0) | (d&7); // CDC mode
@ -251,7 +264,7 @@ static void s68k_reg_write8(u32 a, u32 d)
if ((a&0x1f0) == 0x10 || (a >= 0x38 && a < 0x42)) if ((a&0x1f0) == 0x10 || (a >= 0x38 && a < 0x42))
{ {
dprintf("s68k: invalid write @ %02x?", a); dprintf("s68k FIXME: invalid write @ %02x?", a);
return; return;
} }
@ -260,200 +273,33 @@ static void s68k_reg_write8(u32 a, u32 d)
static u32 OtherRead16End(u32 a, int realsize)
static int PadRead(int i)
{
int pad=0,value=0,TH;
pad=~PicoPad[i]; // Get inverse of pad MXYZ SACB RLDU
TH=Pico.ioports[i+1]&0x40;
if(PicoOpt & 0x20) { // 6 button gamepad enabled
int phase = Pico.m.padTHPhase[i];
if(phase == 2 && !TH) {
value=(pad&0xc0)>>2; // ?0SA 0000
goto end;
} else if(phase == 3 && TH) {
value=(pad&0x30)|((pad>>8)&0xf); // ?1CB MXYZ
goto end;
} else if(phase == 3 && !TH) {
value=((pad&0xc0)>>2)|0x0f; // ?0SA 1111
goto end;
}
}
if(TH) value=(pad&0x3f); // ?1CB RLDU
else value=((pad&0xc0)>>2)|(pad&3); // ?0SA 00DU
end:
// orr the bits, which are set as output
value |= Pico.ioports[i+1]&Pico.ioports[i+4];
return value; // will mirror later
}
static u8 z80Read8(u32 a)
{
if(Pico.m.z80Run&1) return 0;
a&=0x1fff;
if(!(PicoOpt&4)) {
// Z80 disabled, do some faking
static u8 zerosent = 0;
if(a == Pico.m.z80_lastaddr) { // probably polling something
u8 d = Pico.m.z80_fakeval;
if((d & 0xf) == 0xf && !zerosent) {
d = 0; zerosent = 1;
} else {
Pico.m.z80_fakeval++;
zerosent = 0;
}
return d;
} else {
Pico.m.z80_fakeval = 0;
}
}
Pico.m.z80_lastaddr = (u16) a;
return Pico.zram[a];
}
// for nonstandard reads
static u32 UnusualRead16(u32 a, int realsize)
{ {
u32 d=0; u32 d=0;
dprintf("unusual r%i: %06x @%06x", realsize&~1, (a&0xfffffe)+(realsize&1), SekPc);
dprintf("ret = %04x", d);
return d;
}
static u32 OtherRead16(u32 a, int realsize)
{
u32 d=0;
if ((a&0xff0000)==0xa00000) {
if ((a&0x4000)==0x0000) { d=z80Read8(a); d|=d<<8; goto end; } // Z80 ram (not byteswaped)
if ((a&0x6000)==0x4000) { if(PicoOpt&1) d=YM2612Read(); else d=Pico.m.rotate++&3; goto end; } // 0x4000-0x5fff, Fudge if disabled
d=0xffff; goto end;
}
if ((a&0xffffe0)==0xa10000) { // I/O ports
a=(a>>1)&0xf;
switch(a) {
case 0: d=Pico.m.hardware; break; // Hardware value (Version register)
case 1: d=PadRead(0); d|=Pico.ioports[1]&0x80; break;
case 2: d=PadRead(1); d|=Pico.ioports[2]&0x80; break;
default: d=Pico.ioports[a]; break; // IO ports can be used as RAM
}
d|=d<<8;
goto end;
}
// |=0x80 for Shadow of the Beast & Super Offroad; rotate fakes next fetched instruction for Time Killers
if (a==0xa11100) { d=((Pico.m.z80Run&1)<<8)|0x8000|Pico.m.rotate++; goto end; }
if ((a&0xe700e0)==0xc00000) { d=PicoVideoRead(a); goto end; }
if ((a&0xffffc0)==0xa12000) { if ((a&0xffffc0)==0xa12000) {
d=m68k_reg_read16(a); d=m68k_reg_read16(a);
goto end; goto end;
} }
d = UnusualRead16(a, realsize); dprintf("m68k FIXME: unusual r%i: %06x @%06x", realsize&~1, (a&0xfffffe)+(realsize&1), SekPc);
end: end:
return d; return d;
} }
//extern UINT32 mz80GetRegisterValue(void *, UINT32);
static void OtherWrite8(u32 a,u32 d,int realsize) static void OtherWrite8End(u32 a, u32 d, int realsize)
{ {
if ((a&0xe700f9)==0xc00011||(a&0xff7ff9)==0xa07f11) { if(PicoOpt&2) SN76496Write(d); return; } // PSG Sound
if ((a&0xff4000)==0xa00000) { if(!(Pico.m.z80Run&1)) Pico.zram[a&0x1fff]=(u8)d; return; } // Z80 ram
if ((a&0xff6000)==0xa04000) { if(PicoOpt&1) emustatus|=YM2612Write(a&3, d); return; } // FM Sound
if ((a&0xffffe0)==0xa10000) { // I/O ports
a=(a>>1)&0xf;
// 6 button gamepad: if TH went from 0 to 1, gamepad changes state
if(PicoOpt&0x20) {
if(a==1) {
Pico.m.padDelay[0] = 0;
if(!(Pico.ioports[1]&0x40) && (d&0x40)) Pico.m.padTHPhase[0]++;
}
else if(a==2) {
Pico.m.padDelay[1] = 0;
if(!(Pico.ioports[2]&0x40) && (d&0x40)) Pico.m.padTHPhase[1]++;
}
}
Pico.ioports[a]=(u8)d; // IO ports can be used as RAM
return;
}
if (a==0xa11100) {
extern int z80startCycle, z80stopCycle;
//int lineCycles=(488-SekCyclesLeft)&0x1ff;
d&=1; d^=1;
if(!d) {
// hack: detect a nasty situation where Z80 was enabled and disabled in the same 68k timeslice (Golden Axe III)
if((PicoOpt&4) && Pico.m.z80Run==1) z80_run(20);
z80stopCycle = SekCyclesDone();
//z80ExtraCycles += (lineCycles>>1)-(lineCycles>>5); // only meaningful in PicoFrameHints()
} else {
z80startCycle = SekCyclesDone();
//if(Pico.m.scanline != -1)
//z80ExtraCycles -= (lineCycles>>1)-(lineCycles>>5)+16;
}
//dprintf("set_zrun: %i [%i|%i] zPC=%04x @%06x", d, Pico.m.scanline, SekCyclesDone(), mz80GetRegisterValue(NULL, 0), SekPc);
Pico.m.z80Run=(u8)d; return;
}
if (a==0xa11200) { if(!(d&1)) z80_reset(); return; }
if ((a&0xff7f00)==0xa06000) // Z80 BANK register
{
Pico.m.z80_bank68k>>=1;
Pico.m.z80_bank68k|=(d&1)<<8;
Pico.m.z80_bank68k&=0x1ff; // 9 bits and filled in the new top one
return;
}
if ((a&0xe700e0)==0xc00000) { PicoVideoWrite(a,(u16)(d|(d<<8))); return; } // Byte access gets mirrored
if ((a&0xffffc0)==0xa12000) { m68k_reg_write8(a, d); return; } if ((a&0xffffc0)==0xa12000) { m68k_reg_write8(a, d); return; }
dprintf("strange w%i: %06x, %08x @%06x", realsize, a&0xffffff, d, SekPc); dprintf("m68k FIXME: strange w%i: %06x, %08x @%06x", realsize, a&0xffffff, d, SekPc);
} }
static void OtherWrite16(u32 a,u32 d)
{
if ((a&0xe700e0)==0xc00000) { PicoVideoWrite(a,(u16)d); return; }
if ((a&0xff4000)==0xa00000) { if(!(Pico.m.z80Run&1)) Pico.zram[a&0x1fff]=(u8)(d>>8); return; } // Z80 ram (MSB only)
if ((a&0xffffe0)==0xa10000) { // I/O ports #undef _ASM_MEMORY_C
a=(a>>1)&0xf; #include "../MemoryCmn.c"
// 6 button gamepad: if TH went from 0 to 1, gamepad changes state
if(PicoOpt&0x20) {
if(a==1) {
Pico.m.padDelay[0] = 0;
if(!(Pico.ioports[1]&0x40) && (d&0x40)) Pico.m.padTHPhase[0]++;
}
else if(a==2) {
Pico.m.padDelay[1] = 0;
if(!(Pico.ioports[2]&0x40) && (d&0x40)) Pico.m.padTHPhase[1]++;
}
}
Pico.ioports[a]=(u8)d; // IO ports can be used as RAM
return;
}
if (a==0xa11100) { OtherWrite8(a, d>>8, 16); return; }
if (a==0xa11200) { if(!(d&0x100)) z80_reset(); return; }
OtherWrite8(a, d>>8, 16);
OtherWrite8(a+1,d&0xff, 16);
}
// ----------------------------------------------------------------- // -----------------------------------------------------------------
// Read Rom and read Ram // Read Rom and read Ram
@ -495,16 +341,14 @@ u8 PicoReadM68k8(u32 a)
if ((a&0xfc0000)==0x200000) { if ((a&0xfc0000)==0x200000) {
dprintf("m68k_wram r8: [%06x] @%06x", a, SekPc); dprintf("m68k_wram r8: [%06x] @%06x", a, SekPc);
if (Pico_mcd->s68k_regs[3]&4) { // 1M mode? if (Pico_mcd->s68k_regs[3]&4) { // 1M mode?
if (a >= 0x220000) { int bank = Pico_mcd->s68k_regs[3]&1;
dprintf("cell"); if (a >= 0x220000)
} else { a = (a&3) | (cell_map(a >> 2) << 2); // cell arranged
a=((a&0x1fffe)<<1)|(a&1); else a &= 0x1ffff;
if (Pico_mcd->s68k_regs[3]&1) a+=2; d = Pico_mcd->word_ram1M[bank][a^1];
d = Pico_mcd->word_ram[a^1];
}
} else { } else {
// allow access in any mode, like Gens does // allow access in any mode, like Gens does
d = Pico_mcd->word_ram[(a^1)&0x3ffff]; d = Pico_mcd->word_ram2M[(a^1)&0x3ffff];
} }
dprintf("ret = %02x", (u8)d); dprintf("ret = %02x", (u8)d);
goto end; goto end;
@ -550,16 +394,14 @@ u16 PicoReadM68k16(u32 a)
if ((a&0xfc0000)==0x200000) { if ((a&0xfc0000)==0x200000) {
dprintf("m68k_wram r16: [%06x] @%06x", a, SekPc); dprintf("m68k_wram r16: [%06x] @%06x", a, SekPc);
if (Pico_mcd->s68k_regs[3]&4) { // 1M mode? if (Pico_mcd->s68k_regs[3]&4) { // 1M mode?
if (a >= 0x220000) { int bank = Pico_mcd->s68k_regs[3]&1;
dprintf("cell"); if (a >= 0x220000)
} else { a = (a&2) | (cell_map(a >> 2) << 2); // cell arranged
a=((a&0x1fffe)<<1); else a &= 0x1fffe;
if (Pico_mcd->s68k_regs[3]&1) a+=2; d = *(u16 *)(Pico_mcd->word_ram1M[bank]+a);
d = *(u16 *)(Pico_mcd->word_ram+a);
}
} else { } else {
// allow access in any mode, like Gens does // allow access in any mode, like Gens does
d = *(u16 *)(Pico_mcd->word_ram+(a&0x3fffe)); d = *(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe));
} }
dprintf("ret = %04x", d); dprintf("ret = %04x", d);
goto end; goto end;
@ -604,17 +446,20 @@ u32 PicoReadM68k32(u32 a)
if ((a&0xfc0000)==0x200000) { if ((a&0xfc0000)==0x200000) {
dprintf("m68k_wram r32: [%06x] @%06x", a, SekPc); dprintf("m68k_wram r32: [%06x] @%06x", a, SekPc);
if (Pico_mcd->s68k_regs[3]&4) { // 1M mode? if (Pico_mcd->s68k_regs[3]&4) { // 1M mode?
if (a >= 0x220000) { int bank = Pico_mcd->s68k_regs[3]&1;
dprintf("cell"); if (a >= 0x220000) { // cell arranged
u32 a1, a2;
a1 = (a&2) | (cell_map(a >> 2) << 2);
if (a&2) a2 = cell_map((a+2) >> 2) << 2;
else a2 = a1 + 2;
d = *(u16 *)(Pico_mcd->word_ram1M[bank]+a1) << 16;
d |= *(u16 *)(Pico_mcd->word_ram1M[bank]+a2);
} else { } else {
a=((a&0x1fffe)<<1); u16 *pm=(u16 *)(Pico_mcd->word_ram1M[bank]+(a&0x1fffe)); d = (pm[0]<<16)|pm[1];
if (Pico_mcd->s68k_regs[3]&1) a+=2;
d = *(u16 *)(Pico_mcd->word_ram+a) << 16;
d |= *(u16 *)(Pico_mcd->word_ram+a+4);
} }
} else { } else {
// allow access in any mode, like Gens does // allow access in any mode, like Gens does
u16 *pm=(u16 *)(Pico_mcd->word_ram+(a&0x3fffe)); d = (pm[0]<<16)|pm[1]; u16 *pm=(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe)); d = (pm[0]<<16)|pm[1];
} }
dprintf("ret = %08x", d); dprintf("ret = %08x", d);
goto end; goto end;
@ -666,16 +511,14 @@ void PicoWriteM68k8(u32 a,u8 d)
if ((a&0xfc0000)==0x200000) { if ((a&0xfc0000)==0x200000) {
dprintf("m68k_wram w8: [%06x] %02x @%06x", a, d, SekPc); dprintf("m68k_wram w8: [%06x] %02x @%06x", a, d, SekPc);
if (Pico_mcd->s68k_regs[3]&4) { // 1M mode? if (Pico_mcd->s68k_regs[3]&4) { // 1M mode?
if (a >= 0x220000) { int bank = Pico_mcd->s68k_regs[3]&1;
dprintf("cell"); if (a >= 0x220000)
} else { a = (a&3) | (cell_map(a >> 2) << 2); // cell arranged
a=((a&0x1fffe)<<1)|(a&1); else a &= 0x1ffff;
if (Pico_mcd->s68k_regs[3]&1) a+=2; *(u8 *)(Pico_mcd->word_ram1M[bank]+(a^1))=d;
*(u8 *)(Pico_mcd->word_ram+(a^1))=d;
}
} else { } else {
// allow access in any mode, like Gens does // allow access in any mode, like Gens does
*(u8 *)(Pico_mcd->word_ram+((a^1)&0x3ffff))=d; *(u8 *)(Pico_mcd->word_ram2M+((a^1)&0x3ffff))=d;
} }
return; return;
} }
@ -712,16 +555,14 @@ void PicoWriteM68k16(u32 a,u16 d)
if ((a&0xfc0000)==0x200000) { if ((a&0xfc0000)==0x200000) {
dprintf("m68k_wram w16: [%06x] %04x @%06x", a, d, SekPc); dprintf("m68k_wram w16: [%06x] %04x @%06x", a, d, SekPc);
if (Pico_mcd->s68k_regs[3]&4) { // 1M mode? if (Pico_mcd->s68k_regs[3]&4) { // 1M mode?
if (a >= 0x220000) { int bank = Pico_mcd->s68k_regs[3]&1;
dprintf("cell"); if (a >= 0x220000)
} else { a = (a&2) | (cell_map(a >> 2) << 2); // cell arranged
a=((a&0x1fffe)<<1); else a &= 0x1fffe;
if (Pico_mcd->s68k_regs[3]&1) a+=2; *(u16 *)(Pico_mcd->word_ram1M[bank]+a)=d;
*(u16 *)(Pico_mcd->word_ram+a)=d;
}
} else { } else {
// allow access in any mode, like Gens does // allow access in any mode, like Gens does
*(u16 *)(Pico_mcd->word_ram+(a&0x3fffe))=d; *(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe))=d;
} }
return; return;
} }
@ -762,17 +603,21 @@ void PicoWriteM68k32(u32 a,u32 d)
if (d != 0) // don't log clears if (d != 0) // don't log clears
dprintf("m68k_wram w32: [%06x] %08x @%06x", a, d, SekPc); dprintf("m68k_wram w32: [%06x] %08x @%06x", a, d, SekPc);
if (Pico_mcd->s68k_regs[3]&4) { // 1M mode? if (Pico_mcd->s68k_regs[3]&4) { // 1M mode?
if (a >= 0x220000) { int bank = Pico_mcd->s68k_regs[3]&1;
dprintf("cell"); if (a >= 0x220000) { // cell arranged
u32 a1, a2;
a1 = (a&2) | (cell_map(a >> 2) << 2);
if (a&2) a2 = cell_map((a+2) >> 2) << 2;
else a2 = a1 + 2;
*(u16 *)(Pico_mcd->word_ram1M[bank]+a1) = d >> 16;
*(u16 *)(Pico_mcd->word_ram1M[bank]+a2) = d;
} else { } else {
a=((a&0x1fffe)<<1); u16 *pm=(u16 *)(Pico_mcd->word_ram1M[bank]+(a&0x1fffe));
if (Pico_mcd->s68k_regs[3]&1) a+=2; pm[0]=(u16)(d>>16); pm[1]=(u16)d;
*(u16 *)(Pico_mcd->word_ram+a) = d>>16;
*(u16 *)(Pico_mcd->word_ram+a+4) = d;
} }
} else { } else {
// allow access in any mode, like Gens does // allow access in any mode, like Gens does
u16 *pm=(u16 *)(Pico_mcd->word_ram+(a&0x3fffe)); u16 *pm=(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe));
pm[0]=(u16)(d>>16); pm[1]=(u16)d; pm[0]=(u16)(d>>16); pm[1]=(u16)d;
} }
return; return;
@ -815,24 +660,30 @@ u8 PicoReadS68k8(u32 a)
// word RAM (2M area) // word RAM (2M area)
if ((a&0xfc0000)==0x080000) { // 080000-0bffff if ((a&0xfc0000)==0x080000) { // 080000-0bffff
// test: batman returns
dprintf("s68k_wram2M r8: [%06x] @%06x", a, SekPcS68k); dprintf("s68k_wram2M r8: [%06x] @%06x", a, SekPcS68k);
if (Pico_mcd->s68k_regs[3]&4) { // 1M mode? if (Pico_mcd->s68k_regs[3]&4) { // 1M decode mode?
// TODO (decode) int bank = !(Pico_mcd->s68k_regs[3]&1);
dprintf("(decode)"); d = Pico_mcd->word_ram1M[bank][((a>>1)^1)&0x1ffff];
if (a&1) d &= 0x0f;
else d >>= 4;
dprintf("FIXME: decode");
} else { } else {
// allow access in any mode, like Gens does // allow access in any mode, like Gens does
d = Pico_mcd->word_ram[(a^1)&0x3ffff]; d = Pico_mcd->word_ram2M[(a^1)&0x3ffff];
} }
dprintf("ret = %02x", (u8)d); dprintf("ret = %02x", (u8)d);
goto end; goto end;
} }
// word RAM (1M area) // word RAM (1M area)
if ((a&0xfe0000)==0x0c0000 && (Pico_mcd->s68k_regs[3]&4)) { // 0c0000-0dffff if ((a&0xfe0000)==0x0c0000) { // 0c0000-0dffff
int bank;
dprintf("s68k_wram1M r8: [%06x] @%06x", a, SekPcS68k); dprintf("s68k_wram1M r8: [%06x] @%06x", a, SekPcS68k);
a=((a&0x1fffe)<<1)|(a&1); if (!(Pico_mcd->s68k_regs[3]&4))
if (!(Pico_mcd->s68k_regs[3]&1)) a+=2; dprintf("s68k_wram1M FIXME: wrong mode");
d = Pico_mcd->word_ram[a^1]; bank = !(Pico_mcd->s68k_regs[3]&1);
d = Pico_mcd->word_ram1M[bank][(a^1)&0x1ffff];
dprintf("ret = %02x", (u8)d); dprintf("ret = %02x", (u8)d);
goto end; goto end;
} }
@ -895,23 +746,27 @@ u16 PicoReadS68k16(u32 a)
// word RAM (2M area) // word RAM (2M area)
if ((a&0xfc0000)==0x080000) { // 080000-0bffff if ((a&0xfc0000)==0x080000) { // 080000-0bffff
dprintf("s68k_wram2M r16: [%06x] @%06x", a, SekPcS68k); dprintf("s68k_wram2M r16: [%06x] @%06x", a, SekPcS68k);
if (Pico_mcd->s68k_regs[3]&4) { // 1M mode? if (Pico_mcd->s68k_regs[3]&4) { // 1M decode mode?
// TODO (decode) int bank = !(Pico_mcd->s68k_regs[3]&1);
dprintf("(decode)"); d = Pico_mcd->word_ram1M[bank][((a>>1)^1)&0x1ffff];
d |= d << 4; d &= ~0xf0;
dprintf("FIXME: decode");
} else { } else {
// allow access in any mode, like Gens does // allow access in any mode, like Gens does
d = *(u16 *)(Pico_mcd->word_ram+(a&0x3fffe)); d = *(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe));
} }
dprintf("ret = %04x", d); dprintf("ret = %04x", d);
goto end; goto end;
} }
// word RAM (1M area) // word RAM (1M area)
if ((a&0xfe0000)==0x0c0000 && (Pico_mcd->s68k_regs[3]&4)) { // 0c0000-0dffff if ((a&0xfe0000)==0x0c0000) { // 0c0000-0dffff
int bank;
dprintf("s68k_wram1M r16: [%06x] @%06x", a, SekPcS68k); dprintf("s68k_wram1M r16: [%06x] @%06x", a, SekPcS68k);
a=((a&0x1fffe)<<1); if (!(Pico_mcd->s68k_regs[3]&4))
if (!(Pico_mcd->s68k_regs[3]&1)) a+=2; dprintf("s68k_wram1M FIXME: wrong mode");
d = *(u16 *)(Pico_mcd->word_ram+a); bank = !(Pico_mcd->s68k_regs[3]&1);
d = *(u16 *)(Pico_mcd->word_ram1M[bank]+(a&0x1fffe));
dprintf("ret = %04x", d); dprintf("ret = %04x", d);
goto end; goto end;
} }
@ -979,24 +834,29 @@ u32 PicoReadS68k32(u32 a)
// word RAM (2M area) // word RAM (2M area)
if ((a&0xfc0000)==0x080000) { // 080000-0bffff if ((a&0xfc0000)==0x080000) { // 080000-0bffff
dprintf("s68k_wram2M r32: [%06x] @%06x", a, SekPcS68k); dprintf("s68k_wram2M r32: [%06x] @%06x", a, SekPcS68k);
if (Pico_mcd->s68k_regs[3]&4) { // 1M mode? if (Pico_mcd->s68k_regs[3]&4) { // 1M decode mode?
// TODO (decode) int bank = !(Pico_mcd->s68k_regs[3]&1);
dprintf("(decode)"); a >>= 1;
d = Pico_mcd->word_ram1M[bank][((a+0)^1)&0x1ffff] << 16;
d |= Pico_mcd->word_ram1M[bank][((a+1)^1)&0x1ffff];
d |= d << 4; d &= 0x0f0f0f0f;
dprintf("FIXME: decode");
} else { } else {
// allow access in any mode, like Gens does // allow access in any mode, like Gens does
u16 *pm=(u16 *)(Pico_mcd->word_ram+(a&0x3fffe)); d = (pm[0]<<16)|pm[1]; u16 *pm=(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe)); d = (pm[0]<<16)|pm[1];
} }
dprintf("ret = %08x", d); dprintf("ret = %08x", d);
goto end; goto end;
} }
// word RAM (1M area) // word RAM (1M area)
if ((a&0xfe0000)==0x0c0000 && (Pico_mcd->s68k_regs[3]&4)) { // 0c0000-0dffff if ((a&0xfe0000)==0x0c0000) { // 0c0000-0dffff
int bank;
dprintf("s68k_wram1M r32: [%06x] @%06x", a, SekPcS68k); dprintf("s68k_wram1M r32: [%06x] @%06x", a, SekPcS68k);
a=((a&0x1fffe)<<1); if (!(Pico_mcd->s68k_regs[3]&4))
if (!(Pico_mcd->s68k_regs[3]&1)) a+=2; dprintf("s68k_wram1M FIXME: wrong mode");
d = *(u16 *)(Pico_mcd->word_ram+a) << 16; bank = !(Pico_mcd->s68k_regs[3]&1);
d |= *(u16 *)(Pico_mcd->word_ram+a+4); u16 *pm=(u16 *)(Pico_mcd->word_ram1M[bank]+(a&0x1fffe)); d = (pm[0]<<16)|pm[1];
dprintf("ret = %08x", d); dprintf("ret = %08x", d);
goto end; goto end;
} }
@ -1077,23 +937,28 @@ void PicoWriteS68k8(u32 a,u8 d)
// word RAM (2M area) // word RAM (2M area)
if ((a&0xfc0000)==0x080000) { // 080000-0bffff if ((a&0xfc0000)==0x080000) { // 080000-0bffff
dprintf("s68k_wram2M w8: [%06x] %02x @%06x", a, d, SekPcS68k); dprintf("s68k_wram2M w8: [%06x] %02x @%06x", a, d, SekPcS68k);
if (Pico_mcd->s68k_regs[3]&4) { // 1M mode? if (Pico_mcd->s68k_regs[3]&4) { // 1M decode mode?
// TODO (decode) int bank = !(Pico_mcd->s68k_regs[3]&1);
dprintf("(decode)"); if (a&1) d &= 0x0f;
else d >>= 4;
Pico_mcd->word_ram1M[bank][((a>>1)^1)&0x1ffff]=d;
dprintf("FIXME: decode");
} else { } else {
// allow access in any mode, like Gens does // allow access in any mode, like Gens does
*(u8 *)(Pico_mcd->word_ram+((a^1)&0x3ffff))=d; *(u8 *)(Pico_mcd->word_ram2M+((a^1)&0x3ffff))=d;
} }
return; return;
} }
// word RAM (1M area) // word RAM (1M area)
if ((a&0xfe0000)==0x0c0000 && (Pico_mcd->s68k_regs[3]&4)) { // 0c0000-0dffff if ((a&0xfe0000)==0x0c0000) { // 0c0000-0dffff
int bank;
if (d) if (d)
dprintf("s68k_wram1M w8: [%06x] %02x @%06x", a, d, SekPcS68k); dprintf("s68k_wram1M w8: [%06x] %02x @%06x", a, d, SekPcS68k);
a=((a&0x1fffe)<<1)|(a&1); if (!(Pico_mcd->s68k_regs[3]&4))
if (!(Pico_mcd->s68k_regs[3]&1)) a+=2; dprintf("s68k_wram1M FIXME: wrong mode");
*(u8 *)(Pico_mcd->word_ram+(a^1))=d; bank = !(Pico_mcd->s68k_regs[3]&1);
*(u8 *)(Pico_mcd->word_ram1M[bank]+((a^1)&0x1ffff))=d;
return; return;
} }
@ -1152,23 +1017,27 @@ void PicoWriteS68k16(u32 a,u16 d)
// word RAM (2M area) // word RAM (2M area)
if ((a&0xfc0000)==0x080000) { // 080000-0bffff if ((a&0xfc0000)==0x080000) { // 080000-0bffff
dprintf("s68k_wram2M w16: [%06x] %04x @%06x", a, d, SekPcS68k); dprintf("s68k_wram2M w16: [%06x] %04x @%06x", a, d, SekPcS68k);
if (Pico_mcd->s68k_regs[3]&4) { // 1M mode? if (Pico_mcd->s68k_regs[3]&4) { // 1M decode mode?
// TODO (decode) int bank = !(Pico_mcd->s68k_regs[3]&1);
dprintf("(decode)"); d &= ~0xf0; d |= d >> 8;
Pico_mcd->word_ram1M[bank][((a>>1)^1)&0x1ffff] = d;
dprintf("FIXME: decode");
} else { } else {
// allow access in any mode, like Gens does // allow access in any mode, like Gens does
*(u16 *)(Pico_mcd->word_ram+(a&0x3fffe))=d; *(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe))=d;
} }
return; return;
} }
// word RAM (1M area) // word RAM (1M area)
if ((a&0xfe0000)==0x0c0000 && (Pico_mcd->s68k_regs[3]&4)) { // 0c0000-0dffff if ((a&0xfe0000)==0x0c0000) { // 0c0000-0dffff
int bank;
if (d) if (d)
dprintf("s68k_wram1M w16: [%06x] %04x @%06x", a, d, SekPcS68k); dprintf("s68k_wram1M w16: [%06x] %04x @%06x", a, d, SekPcS68k);
a=((a&0x1fffe)<<1); if (!(Pico_mcd->s68k_regs[3]&4))
if (!(Pico_mcd->s68k_regs[3]&1)) a+=2; dprintf("s68k_wram1M FIXME: wrong mode");
*(u16 *)(Pico_mcd->word_ram+a)=d; bank = !(Pico_mcd->s68k_regs[3]&1);
*(u16 *)(Pico_mcd->word_ram1M[bank]+(a&0x1fffe))=d;
return; return;
} }
@ -1230,25 +1099,32 @@ void PicoWriteS68k32(u32 a,u32 d)
// word RAM (2M area) // word RAM (2M area)
if ((a&0xfc0000)==0x080000) { // 080000-0bffff if ((a&0xfc0000)==0x080000) { // 080000-0bffff
dprintf("s68k_wram2M w32: [%06x] %08x @%06x", a, d, SekPcS68k); dprintf("s68k_wram2M w32: [%06x] %08x @%06x", a, d, SekPcS68k);
if (Pico_mcd->s68k_regs[3]&4) { // 1M mode? if (Pico_mcd->s68k_regs[3]&4) { // 1M decode mode?
// TODO (decode) int bank = !(Pico_mcd->s68k_regs[3]&1);
dprintf("(decode)"); a >>= 1;
d &= 0x0f0f0f0f; d |= d >> 4;
Pico_mcd->word_ram1M[bank][((a+0)^1)&0x1ffff] = d >> 16;
Pico_mcd->word_ram1M[bank][((a+1)^1)&0x1ffff] = d;
dprintf("FIXME: decode");
} else { } else {
// allow access in any mode, like Gens does // allow access in any mode, like Gens does
u16 *pm=(u16 *)(Pico_mcd->word_ram+(a&0x3fffe)); u16 *pm=(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe));
pm[0]=(u16)(d>>16); pm[1]=(u16)d; pm[0]=(u16)(d>>16); pm[1]=(u16)d;
} }
return; return;
} }
// word RAM (1M area) // word RAM (1M area)
if ((a&0xfe0000)==0x0c0000 && (Pico_mcd->s68k_regs[3]&4)) { // 0c0000-0dffff if ((a&0xfe0000)==0x0c0000) { // 0c0000-0dffff
int bank;
u16 *pm;
if (d) if (d)
dprintf("s68k_wram1M w32: [%06x] %08x @%06x", a, d, SekPcS68k); dprintf("s68k_wram1M w32: [%06x] %08x @%06x", a, d, SekPcS68k);
a=((a&0x1fffe)<<1); if (!(Pico_mcd->s68k_regs[3]&4))
if (!(Pico_mcd->s68k_regs[3]&1)) a+=2; dprintf("s68k_wram1M FIXME: wrong mode");
*(u16 *)(Pico_mcd->word_ram+a) = d>>16; bank = !(Pico_mcd->s68k_regs[3]&1);
*(u16 *)(Pico_mcd->word_ram+a+4) = d; pm=(u16 *)(Pico_mcd->word_ram1M[bank]+(a&0x1fffe));
pm[0]=(u16)(d>>16); pm[1]=(u16)d;
return; return;
} }
@ -1290,28 +1166,26 @@ void PicoWriteS68k32(u32 a,u32 d)
#if defined(EMU_C68K) #if defined(EMU_C68K)
static __inline int PicoMemBaseM68k(u32 pc) static __inline int PicoMemBaseM68k(u32 pc)
{ {
int membase=0; if ((pc&0xe00000)==0xe00000)
return (int)Pico.ram-(pc&0xff0000); // Program Counter in Ram
if (pc < 0x20000) if (pc < 0x20000)
return (int)Pico_mcd->bios; // Program Counter in BIOS
if ((pc&0xfc0000)==0x200000)
{ {
membase=(int)Pico_mcd->bios; // Program Counter in BIOS if (!(Pico_mcd->s68k_regs[3]&4))
} return (int)Pico_mcd->word_ram2M - 0x200000; // Program Counter in Word Ram
else if ((pc&0xe00000)==0xe00000) if (pc < 0x220000) {
{ int bank = (Pico_mcd->s68k_regs[3]&1);
membase=(int)Pico.ram-(pc&0xff0000); // Program Counter in Ram return (int)Pico_mcd->word_ram1M[bank] - 0x200000;
} }
else if ((pc&0xfc0000)==0x200000 && !(Pico_mcd->s68k_regs[3]&4))
{
membase=(int)Pico_mcd->word_ram-0x200000; // Program Counter in Word Ram
}
else
{
// Error - Program Counter is invalid
dprintf("m68k: unhandled jump to %06x", pc);
membase=(int)Pico.rom;
} }
return membase; // Error - Program Counter is invalid
dprintf("m68k FIXME: unhandled jump to %06x", pc);
return (int)Pico_mcd->bios;
} }
@ -1328,16 +1202,21 @@ static u32 PicoCheckPcM68k(u32 pc)
static __inline int PicoMemBaseS68k(u32 pc) static __inline int PicoMemBaseS68k(u32 pc)
{ {
int membase; if (pc < 0x80000) // PRG RAM
return (int)Pico_mcd->prg_ram;
membase=(int)Pico_mcd->prg_ram; // Program Counter in Prg RAM if ((pc&0xfc0000)==0x080000) // WORD RAM 2M area (assume we are in the right mode..)
if (pc >= 0x80000) return (int)Pico_mcd->word_ram2M - 0x080000;
{
// Error - Program Counter is invalid if ((pc&0xfe0000)==0x0c0000) { // word RAM 1M area
dprintf("s68k: unhandled jump to %06x", pc); int bank = !(Pico_mcd->s68k_regs[3]&1);
return (int)Pico_mcd->word_ram1M[bank] - 0x0c0000;
} }
return membase; // Error - Program Counter is invalid
dprintf("s68k FIXME: unhandled jump to %06x", pc);
return (int)Pico_mcd->prg_ram;
} }
@ -1402,13 +1281,25 @@ unsigned int m68k_read_pcrelative_CD8 (unsigned int a) {
a&=0xffffff; a&=0xffffff;
if(m68ki_cpu_p == &PicoS68kCPU) { if(m68ki_cpu_p == &PicoS68kCPU) {
if (a < 0x80000) return *(u8 *)(Pico_mcd->prg_ram+(a^1)); // PRG Ram if (a < 0x80000) return *(u8 *)(Pico_mcd->prg_ram+(a^1)); // PRG Ram
dprintf("s68k_read_pcrelative_CD8: can't handle %06x", a); if ((a&0xfc0000)==0x080000 && !(Pico_mcd->s68k_regs[3]&4)) // word RAM (2M area: 080000-0bffff)
return *(u8 *)(Pico_mcd->word_ram2M+((a^1)&0x3ffff));
if ((a&0xfe0000)==0x0c0000 && (Pico_mcd->s68k_regs[3]&4)) { // word RAM (1M area: 0c0000-0dffff)
int bank = !(Pico_mcd->s68k_regs[3]&1);
return *(u8 *)(Pico_mcd->word_ram1M[bank]+((a^1)&0x1ffff));
}
dprintf("s68k_read_pcrelative_CD8 FIXME: can't handle %06x", a);
} else { } else {
if(a<0x20000) return *(u8 *)(Pico.rom+(a^1)); // Bios
if((a&0xe00000)==0xe00000) return *(u8 *)(Pico.ram+((a^1)&0xffff)); // Ram if((a&0xe00000)==0xe00000) return *(u8 *)(Pico.ram+((a^1)&0xffff)); // Ram
if(!(Pico_mcd->s68k_regs[3]&4) && (a&0xfc0000)==0x200000) if(a<0x20000) return *(u8 *)(Pico.rom+(a^1)); // Bios
return Pico_mcd->word_ram[(a^1)&0x3fffe]; if((a&0xfc0000)==0x200000) { // word RAM
dprintf("m68k_read_pcrelative_CD8: can't handle %06x", a); if(!(Pico_mcd->s68k_regs[3]&4)) // 2M?
return *(u8 *)(Pico_mcd->word_ram2M+((a^1)&0x3ffff));
else if (a < 0x220000) {
int bank = Pico_mcd->s68k_regs[3]&1;
return *(u8 *)(Pico_mcd->word_ram1M[bank]+((a^1)&0x1ffff));
}
}
dprintf("m68k_read_pcrelative_CD8 FIXME: can't handle %06x", a);
} }
return 0;//(u8) lastread_d; return 0;//(u8) lastread_d;
} }
@ -1416,27 +1307,54 @@ unsigned int m68k_read_pcrelative_CD16(unsigned int a) {
a&=0xffffff; a&=0xffffff;
if(m68ki_cpu_p == &PicoS68kCPU) { if(m68ki_cpu_p == &PicoS68kCPU) {
if (a < 0x80000) return *(u16 *)(Pico_mcd->prg_ram+(a&~1)); // PRG Ram if (a < 0x80000) return *(u16 *)(Pico_mcd->prg_ram+(a&~1)); // PRG Ram
dprintf("s68k_read_pcrelative_CD16: can't handle %06x", a); if ((a&0xfc0000)==0x080000 && !(Pico_mcd->s68k_regs[3]&4)) // word RAM (2M area: 080000-0bffff)
return *(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe));
if ((a&0xfe0000)==0x0c0000 && (Pico_mcd->s68k_regs[3]&4)) { // word RAM (1M area: 0c0000-0dffff)
int bank = !(Pico_mcd->s68k_regs[3]&1);
return *(u16 *)(Pico_mcd->word_ram1M[bank]+(a&0x1fffe));
}
dprintf("s68k_read_pcrelative_CD16 FIXME: can't handle %06x", a);
} else { } else {
if(a<0x20000) return *(u16 *)(Pico.rom+(a&~1)); // Bios
if((a&0xe00000)==0xe00000) return *(u16 *)(Pico.ram+(a&0xfffe)); // Ram if((a&0xe00000)==0xe00000) return *(u16 *)(Pico.ram+(a&0xfffe)); // Ram
if(!(Pico_mcd->s68k_regs[3]&4) && (a&0xfc0000)==0x200000) if(a<0x20000) return *(u16 *)(Pico.rom+(a&~1)); // Bios
return *(u16 *)(Pico_mcd->word_ram+(a&0x3fffe)); if((a&0xfc0000)==0x200000) { // word RAM
dprintf("m68k_read_pcrelative_CD16: can't handle %06x", a); if(!(Pico_mcd->s68k_regs[3]&4)) // 2M?
return *(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe));
else if (a < 0x220000) {
int bank = Pico_mcd->s68k_regs[3]&1;
return *(u16 *)(Pico_mcd->word_ram1M[bank]+(a&0x1fffe));
}
}
dprintf("m68k_read_pcrelative_CD16 FIXME: can't handle %06x", a);
} }
return 0; return 0;
} }
unsigned int m68k_read_pcrelative_CD32(unsigned int a) { unsigned int m68k_read_pcrelative_CD32(unsigned int a) {
u16 *pm;
a&=0xffffff; a&=0xffffff;
if(m68ki_cpu_p == &PicoS68kCPU) { if(m68ki_cpu_p == &PicoS68kCPU) {
if (a < 0x80000) { u16 *pm=(u16 *)(Pico_mcd->prg_ram+(a&~1)); return (pm[0]<<16)|pm[1]; } // PRG Ram if (a < 0x80000) { u16 *pm=(u16 *)(Pico_mcd->prg_ram+(a&~1)); return (pm[0]<<16)|pm[1]; } // PRG Ram
dprintf("s68k_read_pcrelative_CD32: can't handle %06x", a); if ((a&0xfc0000)==0x080000 && !(Pico_mcd->s68k_regs[3]&4)) // word RAM (2M area: 080000-0bffff)
{ pm=(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe)); return (pm[0]<<16)|pm[1]; }
if ((a&0xfe0000)==0x0c0000 && (Pico_mcd->s68k_regs[3]&4)) { // word RAM (1M area: 0c0000-0dffff)
int bank = !(Pico_mcd->s68k_regs[3]&1);
pm=(u16 *)(Pico_mcd->word_ram1M[bank]+(a&0x1fffe));
return (pm[0]<<16)|pm[1];
}
dprintf("s68k_read_pcrelative_CD32 FIXME: can't handle %06x", a);
} else { } else {
if(a<0x20000) { u16 *pm=(u16 *)(Pico.rom+(a&~1)); return (pm[0]<<16)|pm[1]; }
if((a&0xe00000)==0xe00000) { u16 *pm=(u16 *)(Pico.ram+(a&0xfffe)); return (pm[0]<<16)|pm[1]; } // Ram if((a&0xe00000)==0xe00000) { u16 *pm=(u16 *)(Pico.ram+(a&0xfffe)); return (pm[0]<<16)|pm[1]; } // Ram
if(!(Pico_mcd->s68k_regs[3]&4) && (a&0xfc0000)==0x200000) if(a<0x20000) { u16 *pm=(u16 *)(Pico.rom+(a&~1)); return (pm[0]<<16)|pm[1]; }
{ u16 *pm=(u16 *)(Pico_mcd->word_ram+(a&0x3fffe)); return (pm[0]<<16)|pm[1]; } if((a&0xfc0000)==0x200000) { // word RAM
dprintf("m68k_read_pcrelative_CD32: can't handle %06x", a); if(!(Pico_mcd->s68k_regs[3]&4)) // 2M?
{ pm=(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe)); return (pm[0]<<16)|pm[1]; }
else if (a < 0x220000) {
int bank = Pico_mcd->s68k_regs[3]&1;
pm=(u16 *)(Pico_mcd->word_ram1M[bank]+(a&0x1fffe));
return (pm[0]<<16)|pm[1];
}
}
dprintf("m68k_read_pcrelative_CD32 FIXME: can't handle %06x", a);
} }
return 0; return 0;
} }

View file

@ -16,3 +16,41 @@ unsigned char formatted_bram[4*0x10] =
}; };
// offs | 2Mbit | 1Mbit |
// 0 | [ 2M | unused |
// 128K | bit ] | bank0 |
// 256K | unused | bank1 |
void wram_2M_to_1M(unsigned char *m)
{
unsigned short *m1M_b0, *m1M_b1;
unsigned int i, tmp, *m2M;
m2M = (unsigned int *) (m + 0x40000);
m1M_b0 = (unsigned short *) m2M;
m1M_b1 = (unsigned short *) (m + 0x60000);
for (i = 0x40000/4; i; i--)
{
tmp = *(--m2M);
*(--m1M_b0) = tmp;
*(--m1M_b1) = tmp >> 16;
}
}
void wram_1M_to_2M(unsigned char *m)
{
unsigned short *m1M_b0, *m1M_b1;
unsigned int i, tmp, *m2M;
m2M = (unsigned int *) m;
m1M_b0 = (unsigned short *) (m + 0x20000);
m1M_b1 = (unsigned short *) (m + 0x40000);
for (i = 0x40000/4; i; i--)
{
tmp = *m1M_b0++ | (*m1M_b1++ << 16);
*m2M++ = tmp;
}
}

View file

@ -30,9 +30,9 @@ void PicoExitMCD(void)
int PicoResetMCD(int hard) int PicoResetMCD(int hard)
{ {
memset(Pico_mcd->prg_ram, 0, sizeof(Pico_mcd->prg_ram)); memset(Pico_mcd->prg_ram, 0, sizeof(Pico_mcd->prg_ram));
memset(Pico_mcd->word_ram, 0, sizeof(Pico_mcd->word_ram)); memset(Pico_mcd->word_ram2M, 0, sizeof(Pico_mcd->word_ram2M));
memset(Pico_mcd->pcm_ram, 0, sizeof(Pico_mcd->pcm_ram)); memset(Pico_mcd->pcm_ram, 0, sizeof(Pico_mcd->pcm_ram));
if (hard) { if (hard) {
int fmt_size = sizeof(formatted_bram); int fmt_size = sizeof(formatted_bram);
memset(Pico_mcd->bram, 0, sizeof(Pico_mcd->bram)); memset(Pico_mcd->bram, 0, sizeof(Pico_mcd->bram));

38
Pico/cd/cell_map.c Normal file
View file

@ -0,0 +1,38 @@
// 64 x32 x16 x8 x4 x4
static unsigned int cell_map(int celln)
{
int col, row;
switch ((celln >> 12) & 7) { // 0-0x8000
case 0: // x32 cells
case 1:
case 2:
case 3:
col = celln >> 8;
row = celln & 0xff;
break;
case 4: // x16
case 5:
col = celln >> 7;
row = celln & 0x7f;
row |= 0x10000 >> 8;
break;
case 6: // x8
col = celln >> 6;
row = celln & 0x3f;
row |= 0x18000 >> 8;
break;
case 7: // x4
col = celln >> 5;
row = celln & 0x1f;
row |= (celln & 0x7800) >> 6;
break;
default: // just to make compiler happy
col = row = 0;
break;
}
return (col & 0x3f) + row*64;
}

View file

@ -146,7 +146,7 @@ unsigned int gfx_cd_read(unsigned int a)
case 0x62: d = rot_comp.Reg_62; break; case 0x62: d = rot_comp.Reg_62; break;
case 0x64: d = rot_comp.Reg_64; break; case 0x64: d = rot_comp.Reg_64; break;
case 0x66: break; case 0x66: break;
default: dprintf("gfx_cd_read: unexpected address: %02x", a); break; default: dprintf("gfx_cd_read FIXME: unexpected address: %02x", a); break;
} }
dprintf("gfx_cd_read(%02x) = %04x", a, d); dprintf("gfx_cd_read(%02x) = %04x", a, d);
@ -193,13 +193,82 @@ void gfx_cd_write(unsigned int a, unsigned int d)
gfx_cd_start(); gfx_cd_start();
return; return;
default: dprintf("gfx_cd_write: unexpected address: %02x", a); return; default: dprintf("gfx_cd_write FIXME: unexpected address: %02x", a); return;
} }
} }
void gfx_cd_reset(void) void gfx_cd_reset(void)
{ {
memset(&rot_comp.Reg_58, 0, 0/*sizeof(Pico_mcd->rot_comp)*/); memset(&rot_comp.Reg_58, 0, sizeof(rot_comp));
}
// --------------------------------
#include "cell_map.c"
typedef unsigned short u16;
void DmaSlowCell(unsigned int source, unsigned int a, int len, unsigned char inc)
{
unsigned char *base;
unsigned int asrc, a2;
u16 *r;
base = Pico_mcd->word_ram1M[Pico_mcd->s68k_regs[3]&1];
switch (Pico.video.type)
{
case 1: // vram
r = Pico.vram;
for(; len; len--)
{
asrc = cell_map(source >> 2) << 2;
asrc |= source & 2;
// if(a&1) d=(d<<8)|(d>>8); // ??
r[a>>1] = *(u16 *)(base + asrc);
source += 2;
// AutoIncrement
a=(u16)(a+inc);
}
rendstatus|=0x10;
break;
case 3: // cram
Pico.m.dirtyPal = 1;
r = Pico.cram;
for(a2=a&0x7f; len; len--)
{
asrc = cell_map(source >> 2) << 2;
asrc |= source & 2;
r[a2>>1] = *(u16 *)(base + asrc);
source += 2;
// AutoIncrement
a2+=inc;
// good dest?
if(a2 >= 0x80) break;
}
a=(a&0xff00)|a2;
break;
case 5: // vsram[a&0x003f]=d;
r = Pico.vsram;
for(a2=a&0x7f; len; len--)
{
asrc = cell_map(source >> 2) << 2;
asrc |= source & 2;
r[a2>>1] = *(u16 *)(base + asrc);
source += 2;
// AutoIncrement
a2+=inc;
// good dest?
if(a2 >= 0x80) break;
}
a=(a&0xff00)|a2;
break;
}
// remember addr
Pico.video.addr=(u16)a;
} }

View file

@ -40,5 +40,7 @@ void gfx_cd_write(unsigned int a, unsigned int d);
void gfx_cd_reset(void); void gfx_cd_reset(void);
void DmaSlowCell(unsigned int source, unsigned int a, int len, unsigned char inc);
#endif // _GFX_CD_H #endif // _GFX_CD_H

101
Pico/misc.s Normal file
View file

@ -0,0 +1,101 @@
@ vim:filetype=armasm
.global memcpy16 @ unsigned short *dest, unsigned short *src, int count
memcpy16:
eor r3, r0, r1
tst r3, #2
bne mcp16_cant_align
tst r0, #2
ldrneh r3, [r1], #2
subne r2, r2, #1
strneh r3, [r0], #2
subs r2, r2, #4
bmi mcp16_fin
mcp16_loop:
ldmia r1!, {r3,r12}
subs r2, r2, #4
stmia r0!, {r3,r12}
bpl mcp16_loop
mcp16_fin:
tst r2, #2
ldrne r3, [r1], #4
strne r3, [r0], #4
ands r2, r2, #1
bxeq lr
mcp16_cant_align:
ldrh r3, [r1], #2
subs r2, r2, #1
strh r3, [r0], #2
bne mcp16_cant_align
bx lr
.global memcpy32 @ int *dest, int *src, int count
memcpy32:
stmfd sp!, {r4,lr}
subs r2, r2, #4
bmi mcp32_fin
mcp32_loop:
ldmia r1!, {r3,r4,r12,lr}
subs r2, r2, #4
stmia r0!, {r3,r4,r12,lr}
bpl mcp32_loop
mcp32_fin:
tst r2, #3
ldmeqfd sp!, {r4,pc}
tst r2, #1
ldrne r3, [r1], #4
strne r3, [r0], #4
mcp32_no_unal1:
tst r2, #2
ldmneia r1!, {r3,r12}
ldmfd sp!, {r4,lr}
stmneia r0!, {r3,r12}
bx lr
.global memset32 @ int *dest, int c, int count
memset32:
stmfd sp!, {lr}
mov r3, r1
subs r2, r2, #4
bmi mst32_fin
mov r12,r1
mov lr, r1
mst32_loop:
subs r2, r2, #4
stmia r0!, {r1,r3,r12,lr}
bpl mst32_loop
mst32_fin:
tst r2, #1
strne r1, [r0], #4
tst r2, #2
stmneia r0!, {r1,r3}
ldmfd sp!, {lr}
bx lr

View file

@ -248,8 +248,10 @@ int sound_render(int offset, int length)
SN76496Update(PsndOut+offset, length, stereo); SN76496Update(PsndOut+offset, length, stereo);
// Add in the stereo FM buffer // Add in the stereo FM buffer
if (PicoOpt & 1) if (PicoOpt & 1) {
buf32_updated = YM2612UpdateOne(buf32, length, stereo, 1); buf32_updated = YM2612UpdateOne(buf32, length, stereo, 1);
} else
memset32(buf32, 0, length<<stereo);
//printf("active_chs: %02x\n", buf32_updated); //printf("active_chs: %02x\n", buf32_updated);

View file

@ -764,6 +764,12 @@ static int check_save_file(void)
return 0; return 0;
} }
static void emu_state_cb(const char *str)
{
clearArea(0);
blit("", str);
}
static void RunEvents(unsigned int which) static void RunEvents(unsigned int which)
{ {
if(which & 0x1800) { // save or load (but not both) if(which & 0x1800) { // save or load (but not both)
@ -778,7 +784,10 @@ static void RunEvents(unsigned int which)
} }
if (do_it) { if (do_it) {
osd_text(4, 232, (which & 0x1000) ? "LOADING GAME" : "SAVING GAME"); osd_text(4, 232, (which & 0x1000) ? "LOADING GAME" : "SAVING GAME");
PicoStateProgressCB = emu_state_cb;
gp2x_memcpy_all_buffers(gp2x_screen, 0, 320*240*2);
emu_SaveLoadGame((which & 0x1000) >> 12, 0); emu_SaveLoadGame((which & 0x1000) >> 12, 0);
PicoStateProgressCB = NULL;
} }
reset_timing = 1; reset_timing = 1;
@ -1263,20 +1272,11 @@ size_t gzWrite2(void *p, size_t _size, size_t _n, void *file)
} }
static void emu_state_cb(const char *str)
{
clearArea(0);
blit("", str);
}
int emu_SaveLoadGame(int load, int sram) int emu_SaveLoadGame(int load, int sram)
{ {
int ret = 0; int ret = 0;
char saveFname[512]; char saveFname[512];
PicoStateProgressCB = emu_state_cb;
gp2x_memcpy_all_buffers(gp2x_screen, 0, 320*240*2);
// make save filename // make save filename
romfname_ext(saveFname, ""); romfname_ext(saveFname, "");
if(sram) strcat(saveFname, (PicoMCD&1) ? ".brm" : ".srm"); if(sram) strcat(saveFname, (PicoMCD&1) ? ".brm" : ".srm");

View file

@ -1,2 +1,2 @@
#define VERSION "1.14" #define VERSION "1.15"