mirror of
https://github.com/RaySollium99/picodrive.git
synced 2025-09-05 07:17:45 -04:00
32x: built-in BIOS; reset handling; 68k memhandler split
git-svn-id: file:///home/notaz/opt/svn/PicoDrive@801 be3aeb3a-fb24-0410-a615-afba39da0efa
This commit is contained in:
parent
5fadfb1c37
commit
83ff19ec52
7 changed files with 405 additions and 150 deletions
|
@ -41,20 +41,11 @@ void p32x_sh2_write32(unsigned int a, unsigned int d, int id);
|
|||
|
||||
void sh2_reset(SH2 *sh2)
|
||||
{
|
||||
int save_is_slave;
|
||||
void *save_irqcallback;
|
||||
|
||||
save_irqcallback = sh2->irq_callback;
|
||||
save_is_slave = sh2->is_slave;
|
||||
|
||||
memset(sh2, 0, sizeof(SH2));
|
||||
|
||||
sh2->is_slave = save_is_slave;
|
||||
sh2->irq_callback = save_irqcallback;
|
||||
|
||||
sh2->pc = RL(0);
|
||||
sh2->r[15] = RL(4);
|
||||
sh2->sr = I;
|
||||
sh2->vbr = 0;
|
||||
sh2->pending_int_irq = 0;
|
||||
}
|
||||
|
||||
static void sh2_do_irq(SH2 *sh2, int level, int vector)
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
#include "../pico_int.h"
|
||||
#include "../sound/ym2612.h"
|
||||
|
||||
SH2 sh2s[2];
|
||||
struct Pico32x Pico32x;
|
||||
SH2 sh2s[2];
|
||||
|
||||
static void sh2_irq_cb(int id, int level)
|
||||
{
|
||||
|
@ -39,15 +39,12 @@ void Pico32xStartup(void)
|
|||
elprintf(EL_STATUS|EL_32X, "32X startup");
|
||||
|
||||
PicoAHW |= PAHW_32X;
|
||||
PicoMemSetup32x();
|
||||
|
||||
sh2_init(&msh2, 0);
|
||||
msh2.irq_callback = sh2_irq_cb;
|
||||
sh2_reset(&msh2);
|
||||
|
||||
sh2_init(&ssh2, 1);
|
||||
ssh2.irq_callback = sh2_irq_cb;
|
||||
sh2_reset(&ssh2);
|
||||
|
||||
PicoMemSetup32x();
|
||||
|
||||
if (!Pico.m.pal)
|
||||
Pico32x.vdp_regs[0] |= P32XV_nPAL;
|
||||
|
@ -58,6 +55,54 @@ void Pico32xStartup(void)
|
|||
emu_32x_startup();
|
||||
}
|
||||
|
||||
#define HWSWAP(x) (((x) << 16) | ((x) >> 16))
|
||||
void p32x_reset_sh2s(void)
|
||||
{
|
||||
elprintf(EL_32X, "sh2 reset");
|
||||
|
||||
sh2_reset(&msh2);
|
||||
sh2_reset(&ssh2);
|
||||
|
||||
// if we don't have BIOS set, perform it's work here.
|
||||
// MSH2
|
||||
if (p32x_bios_m == NULL) {
|
||||
unsigned int idl_src, idl_dst, idl_size; // initial data load
|
||||
unsigned int vbr;
|
||||
|
||||
// initial data
|
||||
idl_src = HWSWAP(*(unsigned int *)(Pico.rom + 0x3d4)) & ~0xf0000000;
|
||||
idl_dst = HWSWAP(*(unsigned int *)(Pico.rom + 0x3d8)) & ~0xf0000000;
|
||||
idl_size= HWSWAP(*(unsigned int *)(Pico.rom + 0x3dc));
|
||||
if (idl_size > Pico.romsize || idl_src + idl_size > Pico.romsize ||
|
||||
idl_size > 0x40000 || idl_dst + idl_size > 0x40000 || (idl_src & 3) || (idl_dst & 3)) {
|
||||
elprintf(EL_STATUS|EL_ANOMALY, "32x: invalid initial data ptrs: %06x -> %06x, %06x",
|
||||
idl_src, idl_dst, idl_size);
|
||||
}
|
||||
else
|
||||
memcpy(Pico32xMem->sdram + idl_dst, Pico.rom + idl_src, idl_size);
|
||||
|
||||
// GBR/VBR
|
||||
vbr = HWSWAP(*(unsigned int *)(Pico.rom + 0x3e8));
|
||||
sh2_set_gbr(0, 0x20004000);
|
||||
sh2_set_vbr(0, vbr);
|
||||
|
||||
// checksum and M_OK
|
||||
Pico32x.regs[0x28 / 2] = *(unsigned short *)(Pico.rom + 0x18e);
|
||||
// program will set M_OK
|
||||
}
|
||||
|
||||
// SSH2
|
||||
if (p32x_bios_s == NULL) {
|
||||
unsigned int vbr;
|
||||
|
||||
// GBR/VBR
|
||||
vbr = HWSWAP(*(unsigned int *)(Pico.rom + 0x3ec));
|
||||
sh2_set_gbr(1, 0x20004000);
|
||||
sh2_set_vbr(1, vbr);
|
||||
// program will set S_OK
|
||||
}
|
||||
}
|
||||
|
||||
void Pico32xInit(void)
|
||||
{
|
||||
}
|
||||
|
@ -66,7 +111,7 @@ void PicoPower32x(void)
|
|||
{
|
||||
memset(&Pico32x, 0, sizeof(Pico32x));
|
||||
|
||||
Pico32x.regs[0] = 0x0082; // SH2 reset?
|
||||
Pico32x.regs[0] = P32XS_REN|P32XS_nRES; // verified
|
||||
Pico32x.vdp_regs[0x0a/2] = P32XV_VBLK|P32XV_HBLK|P32XV_PEN;
|
||||
Pico32x.sh2_regs[0] = P32XS2_ADEN;
|
||||
}
|
||||
|
@ -82,8 +127,11 @@ void PicoUnload32x(void)
|
|||
|
||||
void PicoReset32x(void)
|
||||
{
|
||||
extern int p32x_csum_faked;
|
||||
p32x_csum_faked = 0; // tmp
|
||||
if (PicoAHW & PAHW_32X) {
|
||||
Pico32x.sh2irqs |= P32XI_VRES;
|
||||
p32x_update_irls();
|
||||
p32x_poll_event(3, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void p32x_start_blank(void)
|
||||
|
@ -129,6 +177,8 @@ static __inline void run_m68k(int cyc)
|
|||
while (SekCycleCnt < SekCycleAim) { \
|
||||
slice = SekCycleCnt; \
|
||||
run_m68k(SekCycleAim - SekCycleCnt); \
|
||||
if (!(Pico32x.regs[0] & P32XS_nRES)) \
|
||||
continue; /* SH2s reseting */ \
|
||||
slice = SekCycleCnt - slice; /* real count from 68k */ \
|
||||
if (SekCycleCnt < SekCycleAim) \
|
||||
elprintf(EL_32X, "slice %d", slice); \
|
||||
|
|
|
@ -1,3 +1,22 @@
|
|||
/*
|
||||
* Register map:
|
||||
* a15100 F....... R.....EA F.....AC N...VHMP 4000 // Fm Ren nrEs Aden Cart heN V H cMd Pwm
|
||||
* a15102 ........ ......SM ? 4002 // intS intM
|
||||
* a15104 ........ ......10 ........ hhhhhhhh 4004 // bk1 bk0 Hint
|
||||
* a15106 F....... .....SDR UE...... .....SDR 4006 // Full 68S Dma Rv fUll[fb] Empt[fb]
|
||||
* a15108 (32bit DREQ src) 4008
|
||||
* a1510c (32bit DREQ dst) 400c
|
||||
* a15110 llllllll llllll00 4010 // DREQ Len
|
||||
* a15112 (16bit FIFO reg) 4012
|
||||
* a15114 ? (16bit VRES clr) 4014
|
||||
* a15116 ? (16bit Vint clr) 4016
|
||||
* a15118 ? (16bit Hint clr) 4018
|
||||
* a1511a ........ .......C (16bit CMD clr) 401a // Cm
|
||||
* a1511c ? (16bit PWM clr) 401c
|
||||
* a1511e ? ? 401e
|
||||
* a15120 (16 bytes comm) 2020
|
||||
* a15130 (PWM) 2030
|
||||
*/
|
||||
#include "../pico_int.h"
|
||||
#include "../memory.h"
|
||||
|
||||
|
@ -10,6 +29,7 @@
|
|||
|
||||
static const char str_mars[] = "MARS";
|
||||
|
||||
void *p32x_bios_g, *p32x_bios_m, *p32x_bios_s;
|
||||
struct Pico32xMem *Pico32xMem;
|
||||
|
||||
static void bank_switch(int b);
|
||||
|
@ -187,18 +207,14 @@ static void p32x_reg_write8(u32 a, u32 d)
|
|||
// for things like bset on comm port
|
||||
m68k_poll.cnt = 0;
|
||||
|
||||
if (a == 1 && !(r[0] & 1)) {
|
||||
r[0] |= 1;
|
||||
Pico32xStartup();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(r[0] & 1))
|
||||
return;
|
||||
|
||||
switch (a) {
|
||||
case 0: // adapter ctl
|
||||
r[0] = (r[0] & 0x83) | ((d << 8) & P32XS_FM);
|
||||
r[0] = (r[0] & ~P32XS_FM) | ((d << 8) & P32XS_FM);
|
||||
return;
|
||||
case 1: // adapter ctl, RES bit writeable
|
||||
if ((d ^ r[0]) & d & P32XS_nRES)
|
||||
p32x_reset_sh2s();
|
||||
r[0] = (r[0] & ~P32XS_nRES) | (d & P32XS_nRES);
|
||||
return;
|
||||
case 3: // irq ctl
|
||||
if ((d & 1) && !(Pico32x.sh2irqi[0] & P32XI_CMD)) {
|
||||
|
@ -249,7 +265,9 @@ static void p32x_reg_write16(u32 a, u32 d)
|
|||
|
||||
switch (a) {
|
||||
case 0x00: // adapter ctl
|
||||
r[0] = (r[0] & 0x83) | (d & P32XS_FM);
|
||||
if ((d ^ r[0]) & d & P32XS_nRES)
|
||||
p32x_reset_sh2s();
|
||||
r[0] = (r[0] & ~(P32XS_FM|P32XS_nRES)) | (d & (P32XS_FM|P32XS_nRES));
|
||||
return;
|
||||
case 0x10: // DREQ len
|
||||
r[a / 2] = d & ~3;
|
||||
|
@ -591,8 +609,10 @@ static void sh2_peripheral_write32(u32 a, u32 d, int id)
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// default 32x handlers
|
||||
u32 PicoRead8_32x(u32 a)
|
||||
// 32x handlers
|
||||
|
||||
// after ADEN
|
||||
static u32 PicoRead8_32x_on(u32 a)
|
||||
{
|
||||
u32 d = 0;
|
||||
if ((a & 0xffc0) == 0x5100) { // a15100
|
||||
|
@ -600,8 +620,8 @@ u32 PicoRead8_32x(u32 a)
|
|||
goto out_16to8;
|
||||
}
|
||||
|
||||
if (!(Pico32x.regs[0] & 1))
|
||||
goto no_vdp;
|
||||
if ((a & 0xfc00) != 0x5000)
|
||||
return PicoRead8_io(a);
|
||||
|
||||
if ((a & 0xfff0) == 0x5180) { // a15180
|
||||
d = p32x_vdp_read16(a);
|
||||
|
@ -613,7 +633,6 @@ u32 PicoRead8_32x(u32 a)
|
|||
goto out_16to8;
|
||||
}
|
||||
|
||||
no_vdp:
|
||||
if ((a & 0xfffc) == 0x30ec) { // a130ec
|
||||
d = str_mars[a & 3];
|
||||
goto out;
|
||||
|
@ -633,7 +652,7 @@ out:
|
|||
return d;
|
||||
}
|
||||
|
||||
u32 PicoRead16_32x(u32 a)
|
||||
static u32 PicoRead16_32x_on(u32 a)
|
||||
{
|
||||
u32 d = 0;
|
||||
if ((a & 0xffc0) == 0x5100) { // a15100
|
||||
|
@ -641,8 +660,8 @@ u32 PicoRead16_32x(u32 a)
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (!(Pico32x.regs[0] & 1))
|
||||
goto no_vdp;
|
||||
if ((a & 0xfc00) != 0x5000)
|
||||
return PicoRead16_io(a);
|
||||
|
||||
if ((a & 0xfff0) == 0x5180) { // a15180
|
||||
d = p32x_vdp_read16(a);
|
||||
|
@ -654,7 +673,110 @@ u32 PicoRead16_32x(u32 a)
|
|||
goto out;
|
||||
}
|
||||
|
||||
no_vdp:
|
||||
if ((a & 0xfffc) == 0x30ec) { // a130ec
|
||||
d = !(a & 2) ? ('M'<<8)|'A' : ('R'<<8)|'S';
|
||||
goto out;
|
||||
}
|
||||
|
||||
elprintf(EL_UIO, "m68k unmapped r16 [%06x] @%06x", a, SekPc);
|
||||
return d;
|
||||
|
||||
out:
|
||||
elprintf(EL_32X, "m68k 32x r16 [%06x] %04x @%06x", a, d, SekPc);
|
||||
return d;
|
||||
}
|
||||
|
||||
static void PicoWrite8_32x_on(u32 a, u32 d)
|
||||
{
|
||||
if ((a & 0xfc00) == 0x5000)
|
||||
elprintf(EL_32X, "m68k 32x w8 [%06x] %02x @%06x", a, d & 0xff, SekPc);
|
||||
|
||||
if ((a & 0xffc0) == 0x5100) { // a15100
|
||||
p32x_reg_write8(a, d);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((a & 0xfc00) != 0x5000) {
|
||||
PicoWrite8_io(a, d);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((a & 0xfff0) == 0x5180) { // a15180
|
||||
p32x_vdp_write8(a, d);
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: verify
|
||||
if ((a & 0xfe00) == 0x5200) { // a15200
|
||||
elprintf(EL_32X|EL_ANOMALY, "m68k 32x PAL w8 [%06x] %02x @%06x", a, d & 0xff, SekPc);
|
||||
((u8 *)Pico32xMem->pal)[(a & 0x1ff) ^ 1] = d;
|
||||
Pico32x.dirty_pal = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
elprintf(EL_UIO, "m68k unmapped w8 [%06x] %02x @%06x", a, d & 0xff, SekPc);
|
||||
}
|
||||
|
||||
static void PicoWrite16_32x_on(u32 a, u32 d)
|
||||
{
|
||||
if ((a & 0xfc00) == 0x5000)
|
||||
elprintf(EL_UIO, "m68k 32x w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
|
||||
|
||||
if ((a & 0xffc0) == 0x5100) { // a15100
|
||||
p32x_reg_write16(a, d);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((a & 0xfc00) != 0x5000) {
|
||||
PicoWrite16_io(a, d);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((a & 0xfff0) == 0x5180) { // a15180
|
||||
p32x_vdp_write16(a, d);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((a & 0xfe00) == 0x5200) { // a15200
|
||||
Pico32xMem->pal[(a & 0x1ff) / 2] = d;
|
||||
Pico32x.dirty_pal = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
elprintf(EL_UIO, "m68k unmapped w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
|
||||
}
|
||||
|
||||
// before ADEN
|
||||
u32 PicoRead8_32x(u32 a)
|
||||
{
|
||||
u32 d = 0;
|
||||
if ((a & 0xffc0) == 0x5100) { // a15100
|
||||
// regs are always readable
|
||||
d = ((u8 *)Pico32x.regs)[(a & 0x3f) ^ 1];
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((a & 0xfffc) == 0x30ec) { // a130ec
|
||||
d = str_mars[a & 3];
|
||||
goto out;
|
||||
}
|
||||
|
||||
elprintf(EL_UIO, "m68k unmapped r8 [%06x] @%06x", a, SekPc);
|
||||
return d;
|
||||
|
||||
out:
|
||||
elprintf(EL_32X, "m68k 32x r8 [%06x] %02x @%06x", a, d, SekPc);
|
||||
return d;
|
||||
}
|
||||
|
||||
u32 PicoRead16_32x(u32 a)
|
||||
{
|
||||
u32 d = 0;
|
||||
if ((a & 0xffc0) == 0x5100) { // a15100
|
||||
d = Pico32x.regs[(a & 0x3f) / 2];
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((a & 0xfffc) == 0x30ec) { // a130ec
|
||||
d = !(a & 2) ? ('M'<<8)|'A' : ('R'<<8)|'S';
|
||||
goto out;
|
||||
|
@ -670,62 +792,60 @@ out:
|
|||
|
||||
void PicoWrite8_32x(u32 a, u32 d)
|
||||
{
|
||||
if ((a & 0xfc00) == 0x5000)
|
||||
elprintf(EL_32X, "m68k 32x w8 [%06x] %02x @%06x", a, d & 0xff, SekPc);
|
||||
|
||||
if ((a & 0xffc0) == 0x5100) { // a15100
|
||||
p32x_reg_write8(a, d);
|
||||
u16 *r = Pico32x.regs;
|
||||
|
||||
elprintf(EL_32X, "m68k 32x w8 [%06x] %02x @%06x", a, d & 0xff, SekPc);
|
||||
a &= 0x3f;
|
||||
if (a == 1) {
|
||||
if ((d ^ r[0]) & d & P32XS_ADEN) {
|
||||
Pico32xStartup();
|
||||
r[0] &= ~P32XS_nRES; // causes reset if specified by this write
|
||||
r[0] |= P32XS_ADEN;
|
||||
p32x_reg_write8(a, d); // forward for reset processing
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(Pico32x.regs[0] & 1))
|
||||
goto no_vdp;
|
||||
|
||||
if ((a & 0xfff0) == 0x5180) { // a15180
|
||||
p32x_vdp_write8(a, d);
|
||||
// allow only COMM for now
|
||||
if ((a & 0x30) == 0x20) {
|
||||
u8 *r8 = (u8 *)r;
|
||||
r8[a ^ 1] = d;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: verify
|
||||
if ((a & 0xfe00) == 0x5200) { // a15200
|
||||
elprintf(EL_32X|EL_ANOMALY, "m68k 32x PAL w8 [%06x] %02x @%06x", a, d & 0xff, SekPc);
|
||||
((u8 *)Pico32xMem->pal)[(a & 0x1ff) ^ 1] = d;
|
||||
Pico32x.dirty_pal = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
no_vdp:
|
||||
elprintf(EL_UIO, "m68k unmapped w8 [%06x] %02x @%06x", a, d & 0xff, SekPc);
|
||||
}
|
||||
|
||||
void PicoWrite16_32x(u32 a, u32 d)
|
||||
{
|
||||
if ((a & 0xfc00) == 0x5000)
|
||||
elprintf(EL_UIO, "m68k 32x w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
|
||||
|
||||
if ((a & 0xffc0) == 0x5100) { // a15100
|
||||
p32x_reg_write16(a, d);
|
||||
u16 *r = Pico32x.regs;
|
||||
|
||||
elprintf(EL_UIO, "m68k 32x w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
|
||||
a &= 0x3e;
|
||||
if (a == 0) {
|
||||
if ((d ^ r[0]) & d & P32XS_ADEN) {
|
||||
Pico32xStartup();
|
||||
r[0] &= ~P32XS_nRES; // causes reset if specified by this write
|
||||
r[0] |= P32XS_ADEN;
|
||||
p32x_reg_write16(a, d); // forward for reset processing
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(Pico32x.regs[0] & 1))
|
||||
goto no_vdp;
|
||||
|
||||
if ((a & 0xfff0) == 0x5180) { // a15180
|
||||
p32x_vdp_write16(a, d);
|
||||
// allow only COMM for now
|
||||
if ((a & 0x30) == 0x20)
|
||||
r[a / 2] = d;
|
||||
return;
|
||||
}
|
||||
|
||||
if ((a & 0xfe00) == 0x5200) { // a15200
|
||||
Pico32xMem->pal[(a & 0x1ff) / 2] = d;
|
||||
Pico32x.dirty_pal = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
no_vdp:
|
||||
elprintf(EL_UIO, "m68k unmapped w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
|
||||
// hint vector is writeable
|
||||
static void PicoWrite8_hint(u32 a, u32 d)
|
||||
{
|
||||
|
@ -1017,25 +1137,62 @@ void p32x_sh2_write32(u32 a, u32 d, int id)
|
|||
p32x_sh2_write16(a + 2, d, id);
|
||||
}
|
||||
|
||||
static const u16 msh2_code[] = {
|
||||
// trap instructions
|
||||
0xaffe, // bra <self>
|
||||
0x0009, // nop
|
||||
// have to wait a bit until m68k initial program finishes clearing stuff
|
||||
// to avoid races with game SH2 code, like in Tempo
|
||||
0xd004, // mov.l @(_m_ok,pc), r0
|
||||
0xd105, // mov.l @(_cnt,pc), r1
|
||||
0xd205, // mov.l @(_start,pc), r2
|
||||
0x71ff, // add #-1, r1
|
||||
0x4115, // cmp/pl r1
|
||||
0x89fc, // bt -2
|
||||
0xc208, // mov.l r0, @(h'20,gbr)
|
||||
0x6822, // mov.l @r2, r8
|
||||
0x482b, // jmp @r8
|
||||
0x0009, // nop
|
||||
('M'<<8)|'_', ('O'<<8)|'K',
|
||||
0x0001, 0x0000,
|
||||
0x2200, 0x03e0 // master start pointer in ROM
|
||||
};
|
||||
|
||||
static const u16 ssh2_code[] = {
|
||||
0xaffe, // bra <self>
|
||||
0x0009, // nop
|
||||
// code to wait for master, in case authentic master BIOS is used
|
||||
0xd104, // mov.l @(_m_ok,pc), r1
|
||||
0xd206, // mov.l @(_start,pc), r2
|
||||
0xc608, // mov.l @(h'20,gbr), r0
|
||||
0x3100, // cmp/eq r0, r1
|
||||
0x8bfc, // bf #-2
|
||||
0xd003, // mov.l @(_s_ok,pc), r0
|
||||
0xc209, // mov.l r0, @(h'24,gbr)
|
||||
0x6822, // mov.l @r2, r8
|
||||
0x482b, // jmp @r8
|
||||
0x0009, // nop
|
||||
('M'<<8)|'_', ('O'<<8)|'K',
|
||||
('S'<<8)|'_', ('O'<<8)|'K',
|
||||
0x2200, 0x03e4 // slave start pointer in ROM
|
||||
};
|
||||
|
||||
#define HWSWAP(x) (((x) << 16) | ((x) >> 16))
|
||||
void PicoMemSetup32x(void)
|
||||
static void get_bios(void)
|
||||
{
|
||||
unsigned short *ps;
|
||||
unsigned int *pl;
|
||||
unsigned int rs;
|
||||
u16 *ps;
|
||||
u32 *pl;
|
||||
int i;
|
||||
|
||||
Pico32xMem = calloc(1, sizeof(*Pico32xMem));
|
||||
if (Pico32xMem == NULL) {
|
||||
elprintf(EL_STATUS, "OOM");
|
||||
return;
|
||||
// M68K ROM
|
||||
if (p32x_bios_g != NULL) {
|
||||
elprintf(EL_STATUS|EL_32X, "32x: using supplied 68k BIOS");
|
||||
Byteswap(Pico32xMem->m68k_rom, p32x_bios_g, 0x100);
|
||||
}
|
||||
|
||||
dmac0 = (void *)&Pico32xMem->sh2_peri_regs[0][0x180 / 4];
|
||||
|
||||
else {
|
||||
// generate 68k ROM
|
||||
ps = (unsigned short *)Pico32xMem->m68k_rom;
|
||||
pl = (unsigned int *)Pico32xMem->m68k_rom;
|
||||
ps = (u16 *)Pico32xMem->m68k_rom;
|
||||
pl = (u32 *)ps;
|
||||
for (i = 1; i < 0xc0/4; i++)
|
||||
pl[i] = HWSWAP(0x880200 + (i - 1) * 6);
|
||||
|
||||
|
@ -1050,41 +1207,67 @@ void PicoMemSetup32x(void)
|
|||
#else
|
||||
ps[0xfe/2] = 0x4e75; // rts
|
||||
#endif
|
||||
|
||||
// fill remaining mem with ROM
|
||||
}
|
||||
// fill remaining m68k_rom page with game ROM
|
||||
memcpy(Pico32xMem->m68k_rom + 0x100, Pico.rom + 0x100, sizeof(Pico32xMem->m68k_rom) - 0x100);
|
||||
|
||||
// 32X ROM
|
||||
// TODO: move
|
||||
{
|
||||
FILE *f = fopen("32X_M_BIOS.BIN", "rb");
|
||||
int i;
|
||||
if (f == NULL) {
|
||||
printf("missing 32X_M_BIOS.BIN\n");
|
||||
exit(1);
|
||||
// MSH2
|
||||
if (p32x_bios_m != NULL) {
|
||||
elprintf(EL_STATUS|EL_32X, "32x: using supplied master SH2 BIOS");
|
||||
Byteswap(Pico32xMem->sh2_rom_m, p32x_bios_m, sizeof(Pico32xMem->sh2_rom_m));
|
||||
}
|
||||
fread(Pico32xMem->sh2_rom_m, 1, sizeof(Pico32xMem->sh2_rom_m), f);
|
||||
fclose(f);
|
||||
f = fopen("32X_S_BIOS.BIN", "rb");
|
||||
if (f == NULL) {
|
||||
printf("missing 32X_S_BIOS.BIN\n");
|
||||
exit(1);
|
||||
else {
|
||||
pl = (u32 *)Pico32xMem->sh2_rom_m;
|
||||
|
||||
// fill exception vector table to our trap address
|
||||
for (i = 0; i < 128; i++)
|
||||
pl[i] = HWSWAP(0x200);
|
||||
|
||||
// startup code
|
||||
memcpy(Pico32xMem->sh2_rom_m + 0x200, msh2_code, sizeof(msh2_code));
|
||||
|
||||
// reset SP
|
||||
pl[1] = pl[3] = HWSWAP(0x6040000);
|
||||
// start
|
||||
pl[0] = pl[2] = HWSWAP(0x204);
|
||||
}
|
||||
fread(Pico32xMem->sh2_rom_s, 1, sizeof(Pico32xMem->sh2_rom_s), f);
|
||||
fclose(f);
|
||||
// byteswap
|
||||
for (i = 0; i < sizeof(Pico32xMem->sh2_rom_m); i += 2) {
|
||||
int t = Pico32xMem->sh2_rom_m[i];
|
||||
Pico32xMem->sh2_rom_m[i] = Pico32xMem->sh2_rom_m[i + 1];
|
||||
Pico32xMem->sh2_rom_m[i + 1] = t;
|
||||
|
||||
// SSH2
|
||||
if (p32x_bios_s != NULL) {
|
||||
elprintf(EL_STATUS|EL_32X, "32x: using supplied slave SH2 BIOS");
|
||||
Byteswap(Pico32xMem->sh2_rom_s, p32x_bios_s, sizeof(Pico32xMem->sh2_rom_s));
|
||||
}
|
||||
for (i = 0; i < sizeof(Pico32xMem->sh2_rom_s); i += 2) {
|
||||
int t = Pico32xMem->sh2_rom_s[i];
|
||||
Pico32xMem->sh2_rom_s[i] = Pico32xMem->sh2_rom_s[i + 1];
|
||||
Pico32xMem->sh2_rom_s[i + 1] = t;
|
||||
else {
|
||||
pl = (u32 *)Pico32xMem->sh2_rom_s;
|
||||
|
||||
// fill exception vector table to our trap address
|
||||
for (i = 0; i < 128; i++)
|
||||
pl[i] = HWSWAP(0x200);
|
||||
|
||||
// startup code
|
||||
memcpy(Pico32xMem->sh2_rom_s + 0x200, ssh2_code, sizeof(ssh2_code));
|
||||
|
||||
// reset SP
|
||||
pl[1] = pl[3] = HWSWAP(0x603f800);
|
||||
// start
|
||||
pl[0] = pl[2] = HWSWAP(0x204);
|
||||
}
|
||||
}
|
||||
|
||||
void PicoMemSetup32x(void)
|
||||
{
|
||||
unsigned int rs;
|
||||
|
||||
Pico32xMem = calloc(1, sizeof(*Pico32xMem));
|
||||
if (Pico32xMem == NULL) {
|
||||
elprintf(EL_STATUS, "OOM");
|
||||
return;
|
||||
}
|
||||
|
||||
dmac0 = (void *)&Pico32xMem->sh2_peri_regs[0][0x180 / 4];
|
||||
|
||||
get_bios();
|
||||
|
||||
// cartridge area becomes unmapped
|
||||
// XXX: we take the easy way and don't unmap ROM,
|
||||
// so that we can avoid handling the RV bit.
|
||||
|
@ -1110,6 +1293,12 @@ void PicoMemSetup32x(void)
|
|||
// 32X ROM (banked)
|
||||
bank_switch(0);
|
||||
|
||||
// SYS regs
|
||||
cpu68k_map_set(m68k_read8_map, 0xa10000, 0xa1ffff, PicoRead8_32x_on, 1);
|
||||
cpu68k_map_set(m68k_read16_map, 0xa10000, 0xa1ffff, PicoRead16_32x_on, 1);
|
||||
cpu68k_map_set(m68k_write8_map, 0xa10000, 0xa1ffff, PicoWrite8_32x_on, 1);
|
||||
cpu68k_map_set(m68k_write16_map, 0xa10000, 0xa1ffff, PicoWrite16_32x_on, 1);
|
||||
|
||||
// setup poll detector
|
||||
m68k_poll.flag = P32XF_68KPOLL;
|
||||
m68k_poll.cyc_max = 64;
|
||||
|
|
30
pico/cart.c
30
pico/cart.c
|
@ -378,23 +378,21 @@ int pm_close(pm_file *fp)
|
|||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static void Byteswap(unsigned char *data,int len)
|
||||
// byteswap, data needs to be int aligned, src can match dst
|
||||
void Byteswap(void *dst, const void *src, int len)
|
||||
{
|
||||
int i=0;
|
||||
const unsigned int *ps = src;
|
||||
unsigned int *pd = dst;
|
||||
int i, m;
|
||||
|
||||
if (len<2) return; // Too short
|
||||
if (len < 2)
|
||||
return;
|
||||
|
||||
do
|
||||
{
|
||||
unsigned short *pd=(unsigned short *)(data+i);
|
||||
int value=*pd; // Get 2 bytes
|
||||
|
||||
value=(value<<8)|(value>>8); // Byteswap it
|
||||
*pd=(unsigned short)value; // Put 2b ytes
|
||||
i+=2;
|
||||
m = 0x00ff00ff;
|
||||
for (i = 0; i < len / 4; i++) {
|
||||
unsigned int t = ps[i];
|
||||
pd[i] = ((t & m) << 8) | ((t & ~m) >> 8);
|
||||
}
|
||||
while (i+2<=len);
|
||||
}
|
||||
|
||||
// Interleve a 16k block and byteswap
|
||||
|
@ -524,7 +522,7 @@ int PicoCartLoad(pm_file *f,unsigned char **prom,unsigned int *psize,int is_sms)
|
|||
elprintf(EL_STATUS, "SMD format detected.");
|
||||
DecodeSmd(rom,size); size-=0x200; // Decode and byteswap SMD
|
||||
}
|
||||
else Byteswap(rom,size); // Just byteswap
|
||||
else Byteswap(rom, rom, size); // Just byteswap
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -621,9 +619,9 @@ static unsigned int rom_crc32(void)
|
|||
elprintf(EL_STATUS, "caclulating CRC32..");
|
||||
|
||||
// have to unbyteswap for calculation..
|
||||
Byteswap(Pico.rom, Pico.romsize);
|
||||
Byteswap(Pico.rom, Pico.rom, Pico.romsize);
|
||||
crc = crc32(0, Pico.rom, Pico.romsize);
|
||||
Byteswap(Pico.rom, Pico.romsize);
|
||||
Byteswap(Pico.rom, Pico.rom, Pico.romsize);
|
||||
return crc;
|
||||
}
|
||||
|
||||
|
|
|
@ -37,6 +37,10 @@ extern void emu_video_mode_change(int start_line, int line_count, int is_32cols)
|
|||
// this must switch to 32bpp mode
|
||||
extern void emu_32x_startup(void);
|
||||
|
||||
// optional 32X BIOS, should be left NULL if not used
|
||||
// must be 256, 2048, 1024 bytes
|
||||
extern void *p32x_bios_g, *p32x_bios_m, *p32x_bios_s;
|
||||
|
||||
// Pico.c
|
||||
#define POPT_EN_FM (1<< 0) // 00 000x
|
||||
#define POPT_EN_PSG (1<< 1)
|
||||
|
|
|
@ -252,6 +252,11 @@ extern SH2 sh2s[2];
|
|||
#define sh2_vbr(c) (c) ? ssh2.vbr : msh2.vbr
|
||||
#define sh2_sr(c) (c) ? ssh2.sr : msh2.sr
|
||||
|
||||
#define sh2_set_gbr(c, v) \
|
||||
{ if (c) ssh2.gbr = v; else msh2.gbr = v; }
|
||||
#define sh2_set_vbr(c, v) \
|
||||
{ if (c) ssh2.vbr = v; else msh2.vbr = v; }
|
||||
|
||||
// ---------------------------------------------------------
|
||||
|
||||
// main oscillator clock which controls timing
|
||||
|
@ -416,6 +421,9 @@ typedef struct
|
|||
|
||||
// 32X
|
||||
#define P32XS_FM (1<<15)
|
||||
#define P32XS_REN (1<< 7)
|
||||
#define P32XS_nRES (1<< 1)
|
||||
#define P32XS_ADEN (1<< 0)
|
||||
#define P32XS2_ADEN (1<< 9)
|
||||
#define P32XS_FULL (1<< 7) // DREQ FIFO full
|
||||
#define P32XS_68S (1<< 2)
|
||||
|
@ -514,6 +522,7 @@ extern areaseek *areaSeek;
|
|||
extern areaclose *areaClose;
|
||||
|
||||
// cart.c
|
||||
void Byteswap(void *dst, const void *src, int len);
|
||||
extern void (*PicoCartMemSetup)(void);
|
||||
extern void (*PicoCartUnloadHook)(void);
|
||||
|
||||
|
@ -680,6 +689,7 @@ void Pico32xStartup(void);
|
|||
void PicoUnload32x(void);
|
||||
void PicoFrame32x(void);
|
||||
void p32x_update_irls(void);
|
||||
void p32x_reset_sh2s(void);
|
||||
|
||||
// 32x/memory.c
|
||||
struct Pico32xMem *Pico32xMem;
|
||||
|
|
|
@ -1299,6 +1299,19 @@ void emu_init(void)
|
|||
char path[512];
|
||||
int pos;
|
||||
|
||||
#if 0
|
||||
// FIXME: handle through menu, etc
|
||||
FILE *f;
|
||||
f = fopen("32X_M_BIOS.BIN", "rb");
|
||||
p32x_bios_m = malloc(2048);
|
||||
fread(p32x_bios_m, 1, 2048, f);
|
||||
fclose(f);
|
||||
f = fopen("32X_S_BIOS.BIN", "rb");
|
||||
p32x_bios_s = malloc(1024);
|
||||
fread(p32x_bios_s, 1, 1024, f);
|
||||
fclose(f);
|
||||
#endif
|
||||
|
||||
/* make dirs for saves */
|
||||
pos = plat_get_root_dir(path, sizeof(path) - 4);
|
||||
mkdir_path(path, pos, "mds");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue