mirror of
https://github.com/RaySollium99/picodrive.git
synced 2025-09-05 15:27:46 -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)
|
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->pc = RL(0);
|
||||||
sh2->r[15] = RL(4);
|
sh2->r[15] = RL(4);
|
||||||
sh2->sr = I;
|
sh2->sr = I;
|
||||||
|
sh2->vbr = 0;
|
||||||
|
sh2->pending_int_irq = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sh2_do_irq(SH2 *sh2, int level, int vector)
|
static void sh2_do_irq(SH2 *sh2, int level, int vector)
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#include "../pico_int.h"
|
#include "../pico_int.h"
|
||||||
#include "../sound/ym2612.h"
|
#include "../sound/ym2612.h"
|
||||||
|
|
||||||
SH2 sh2s[2];
|
|
||||||
struct Pico32x Pico32x;
|
struct Pico32x Pico32x;
|
||||||
|
SH2 sh2s[2];
|
||||||
|
|
||||||
static void sh2_irq_cb(int id, int level)
|
static void sh2_irq_cb(int id, int level)
|
||||||
{
|
{
|
||||||
|
@ -39,15 +39,12 @@ void Pico32xStartup(void)
|
||||||
elprintf(EL_STATUS|EL_32X, "32X startup");
|
elprintf(EL_STATUS|EL_32X, "32X startup");
|
||||||
|
|
||||||
PicoAHW |= PAHW_32X;
|
PicoAHW |= PAHW_32X;
|
||||||
PicoMemSetup32x();
|
|
||||||
|
|
||||||
sh2_init(&msh2, 0);
|
sh2_init(&msh2, 0);
|
||||||
msh2.irq_callback = sh2_irq_cb;
|
msh2.irq_callback = sh2_irq_cb;
|
||||||
sh2_reset(&msh2);
|
|
||||||
|
|
||||||
sh2_init(&ssh2, 1);
|
sh2_init(&ssh2, 1);
|
||||||
ssh2.irq_callback = sh2_irq_cb;
|
ssh2.irq_callback = sh2_irq_cb;
|
||||||
sh2_reset(&ssh2);
|
|
||||||
|
PicoMemSetup32x();
|
||||||
|
|
||||||
if (!Pico.m.pal)
|
if (!Pico.m.pal)
|
||||||
Pico32x.vdp_regs[0] |= P32XV_nPAL;
|
Pico32x.vdp_regs[0] |= P32XV_nPAL;
|
||||||
|
@ -58,6 +55,54 @@ void Pico32xStartup(void)
|
||||||
emu_32x_startup();
|
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)
|
void Pico32xInit(void)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -66,7 +111,7 @@ void PicoPower32x(void)
|
||||||
{
|
{
|
||||||
memset(&Pico32x, 0, sizeof(Pico32x));
|
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.vdp_regs[0x0a/2] = P32XV_VBLK|P32XV_HBLK|P32XV_PEN;
|
||||||
Pico32x.sh2_regs[0] = P32XS2_ADEN;
|
Pico32x.sh2_regs[0] = P32XS2_ADEN;
|
||||||
}
|
}
|
||||||
|
@ -82,8 +127,11 @@ void PicoUnload32x(void)
|
||||||
|
|
||||||
void PicoReset32x(void)
|
void PicoReset32x(void)
|
||||||
{
|
{
|
||||||
extern int p32x_csum_faked;
|
if (PicoAHW & PAHW_32X) {
|
||||||
p32x_csum_faked = 0; // tmp
|
Pico32x.sh2irqs |= P32XI_VRES;
|
||||||
|
p32x_update_irls();
|
||||||
|
p32x_poll_event(3, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void p32x_start_blank(void)
|
static void p32x_start_blank(void)
|
||||||
|
@ -129,6 +177,8 @@ static __inline void run_m68k(int cyc)
|
||||||
while (SekCycleCnt < SekCycleAim) { \
|
while (SekCycleCnt < SekCycleAim) { \
|
||||||
slice = SekCycleCnt; \
|
slice = SekCycleCnt; \
|
||||||
run_m68k(SekCycleAim - SekCycleCnt); \
|
run_m68k(SekCycleAim - SekCycleCnt); \
|
||||||
|
if (!(Pico32x.regs[0] & P32XS_nRES)) \
|
||||||
|
continue; /* SH2s reseting */ \
|
||||||
slice = SekCycleCnt - slice; /* real count from 68k */ \
|
slice = SekCycleCnt - slice; /* real count from 68k */ \
|
||||||
if (SekCycleCnt < SekCycleAim) \
|
if (SekCycleCnt < SekCycleAim) \
|
||||||
elprintf(EL_32X, "slice %d", slice); \
|
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 "../pico_int.h"
|
||||||
#include "../memory.h"
|
#include "../memory.h"
|
||||||
|
|
||||||
|
@ -10,6 +29,7 @@
|
||||||
|
|
||||||
static const char str_mars[] = "MARS";
|
static const char str_mars[] = "MARS";
|
||||||
|
|
||||||
|
void *p32x_bios_g, *p32x_bios_m, *p32x_bios_s;
|
||||||
struct Pico32xMem *Pico32xMem;
|
struct Pico32xMem *Pico32xMem;
|
||||||
|
|
||||||
static void bank_switch(int b);
|
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
|
// for things like bset on comm port
|
||||||
m68k_poll.cnt = 0;
|
m68k_poll.cnt = 0;
|
||||||
|
|
||||||
if (a == 1 && !(r[0] & 1)) {
|
|
||||||
r[0] |= 1;
|
|
||||||
Pico32xStartup();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(r[0] & 1))
|
|
||||||
return;
|
|
||||||
|
|
||||||
switch (a) {
|
switch (a) {
|
||||||
case 0: // adapter ctl
|
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;
|
return;
|
||||||
case 3: // irq ctl
|
case 3: // irq ctl
|
||||||
if ((d & 1) && !(Pico32x.sh2irqi[0] & P32XI_CMD)) {
|
if ((d & 1) && !(Pico32x.sh2irqi[0] & P32XI_CMD)) {
|
||||||
|
@ -249,7 +265,9 @@ static void p32x_reg_write16(u32 a, u32 d)
|
||||||
|
|
||||||
switch (a) {
|
switch (a) {
|
||||||
case 0x00: // adapter ctl
|
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;
|
return;
|
||||||
case 0x10: // DREQ len
|
case 0x10: // DREQ len
|
||||||
r[a / 2] = d & ~3;
|
r[a / 2] = d & ~3;
|
||||||
|
@ -591,8 +609,10 @@ static void sh2_peripheral_write32(u32 a, u32 d, int id)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
// default 32x handlers
|
// 32x handlers
|
||||||
u32 PicoRead8_32x(u32 a)
|
|
||||||
|
// after ADEN
|
||||||
|
static u32 PicoRead8_32x_on(u32 a)
|
||||||
{
|
{
|
||||||
u32 d = 0;
|
u32 d = 0;
|
||||||
if ((a & 0xffc0) == 0x5100) { // a15100
|
if ((a & 0xffc0) == 0x5100) { // a15100
|
||||||
|
@ -600,8 +620,8 @@ u32 PicoRead8_32x(u32 a)
|
||||||
goto out_16to8;
|
goto out_16to8;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(Pico32x.regs[0] & 1))
|
if ((a & 0xfc00) != 0x5000)
|
||||||
goto no_vdp;
|
return PicoRead8_io(a);
|
||||||
|
|
||||||
if ((a & 0xfff0) == 0x5180) { // a15180
|
if ((a & 0xfff0) == 0x5180) { // a15180
|
||||||
d = p32x_vdp_read16(a);
|
d = p32x_vdp_read16(a);
|
||||||
|
@ -613,7 +633,6 @@ u32 PicoRead8_32x(u32 a)
|
||||||
goto out_16to8;
|
goto out_16to8;
|
||||||
}
|
}
|
||||||
|
|
||||||
no_vdp:
|
|
||||||
if ((a & 0xfffc) == 0x30ec) { // a130ec
|
if ((a & 0xfffc) == 0x30ec) { // a130ec
|
||||||
d = str_mars[a & 3];
|
d = str_mars[a & 3];
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -633,7 +652,7 @@ out:
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 PicoRead16_32x(u32 a)
|
static u32 PicoRead16_32x_on(u32 a)
|
||||||
{
|
{
|
||||||
u32 d = 0;
|
u32 d = 0;
|
||||||
if ((a & 0xffc0) == 0x5100) { // a15100
|
if ((a & 0xffc0) == 0x5100) { // a15100
|
||||||
|
@ -641,8 +660,8 @@ u32 PicoRead16_32x(u32 a)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(Pico32x.regs[0] & 1))
|
if ((a & 0xfc00) != 0x5000)
|
||||||
goto no_vdp;
|
return PicoRead16_io(a);
|
||||||
|
|
||||||
if ((a & 0xfff0) == 0x5180) { // a15180
|
if ((a & 0xfff0) == 0x5180) { // a15180
|
||||||
d = p32x_vdp_read16(a);
|
d = p32x_vdp_read16(a);
|
||||||
|
@ -654,7 +673,110 @@ u32 PicoRead16_32x(u32 a)
|
||||||
goto out;
|
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
|
if ((a & 0xfffc) == 0x30ec) { // a130ec
|
||||||
d = !(a & 2) ? ('M'<<8)|'A' : ('R'<<8)|'S';
|
d = !(a & 2) ? ('M'<<8)|'A' : ('R'<<8)|'S';
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -670,62 +792,60 @@ out:
|
||||||
|
|
||||||
void PicoWrite8_32x(u32 a, u32 d)
|
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
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(Pico32x.regs[0] & 1))
|
// allow only COMM for now
|
||||||
goto no_vdp;
|
if ((a & 0x30) == 0x20) {
|
||||||
|
u8 *r8 = (u8 *)r;
|
||||||
if ((a & 0xfff0) == 0x5180) { // a15180
|
r8[a ^ 1] = d;
|
||||||
p32x_vdp_write8(a, d);
|
}
|
||||||
return;
|
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);
|
elprintf(EL_UIO, "m68k unmapped w8 [%06x] %02x @%06x", a, d & 0xff, SekPc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PicoWrite16_32x(u32 a, u32 d)
|
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
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(Pico32x.regs[0] & 1))
|
// allow only COMM for now
|
||||||
goto no_vdp;
|
if ((a & 0x30) == 0x20)
|
||||||
|
r[a / 2] = d;
|
||||||
if ((a & 0xfff0) == 0x5180) { // a15180
|
|
||||||
p32x_vdp_write16(a, d);
|
|
||||||
return;
|
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);
|
elprintf(EL_UIO, "m68k unmapped w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
|
||||||
// hint vector is writeable
|
// hint vector is writeable
|
||||||
static void PicoWrite8_hint(u32 a, u32 d)
|
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);
|
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))
|
#define HWSWAP(x) (((x) << 16) | ((x) >> 16))
|
||||||
void PicoMemSetup32x(void)
|
static void get_bios(void)
|
||||||
{
|
{
|
||||||
unsigned short *ps;
|
u16 *ps;
|
||||||
unsigned int *pl;
|
u32 *pl;
|
||||||
unsigned int rs;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
Pico32xMem = calloc(1, sizeof(*Pico32xMem));
|
// M68K ROM
|
||||||
if (Pico32xMem == NULL) {
|
if (p32x_bios_g != NULL) {
|
||||||
elprintf(EL_STATUS, "OOM");
|
elprintf(EL_STATUS|EL_32X, "32x: using supplied 68k BIOS");
|
||||||
return;
|
Byteswap(Pico32xMem->m68k_rom, p32x_bios_g, 0x100);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
dmac0 = (void *)&Pico32xMem->sh2_peri_regs[0][0x180 / 4];
|
|
||||||
|
|
||||||
// generate 68k ROM
|
// generate 68k ROM
|
||||||
ps = (unsigned short *)Pico32xMem->m68k_rom;
|
ps = (u16 *)Pico32xMem->m68k_rom;
|
||||||
pl = (unsigned int *)Pico32xMem->m68k_rom;
|
pl = (u32 *)ps;
|
||||||
for (i = 1; i < 0xc0/4; i++)
|
for (i = 1; i < 0xc0/4; i++)
|
||||||
pl[i] = HWSWAP(0x880200 + (i - 1) * 6);
|
pl[i] = HWSWAP(0x880200 + (i - 1) * 6);
|
||||||
|
|
||||||
|
@ -1050,41 +1207,67 @@ void PicoMemSetup32x(void)
|
||||||
#else
|
#else
|
||||||
ps[0xfe/2] = 0x4e75; // rts
|
ps[0xfe/2] = 0x4e75; // rts
|
||||||
#endif
|
#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);
|
memcpy(Pico32xMem->m68k_rom + 0x100, Pico.rom + 0x100, sizeof(Pico32xMem->m68k_rom) - 0x100);
|
||||||
|
|
||||||
// 32X ROM
|
// MSH2
|
||||||
// TODO: move
|
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));
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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));
|
||||||
|
}
|
||||||
|
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)
|
||||||
{
|
{
|
||||||
FILE *f = fopen("32X_M_BIOS.BIN", "rb");
|
unsigned int rs;
|
||||||
int i;
|
|
||||||
if (f == NULL) {
|
Pico32xMem = calloc(1, sizeof(*Pico32xMem));
|
||||||
printf("missing 32X_M_BIOS.BIN\n");
|
if (Pico32xMem == NULL) {
|
||||||
exit(1);
|
elprintf(EL_STATUS, "OOM");
|
||||||
}
|
return;
|
||||||
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);
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dmac0 = (void *)&Pico32xMem->sh2_peri_regs[0][0x180 / 4];
|
||||||
|
|
||||||
|
get_bios();
|
||||||
|
|
||||||
// cartridge area becomes unmapped
|
// cartridge area becomes unmapped
|
||||||
// XXX: we take the easy way and don't unmap ROM,
|
// XXX: we take the easy way and don't unmap ROM,
|
||||||
// so that we can avoid handling the RV bit.
|
// so that we can avoid handling the RV bit.
|
||||||
|
@ -1110,6 +1293,12 @@ void PicoMemSetup32x(void)
|
||||||
// 32X ROM (banked)
|
// 32X ROM (banked)
|
||||||
bank_switch(0);
|
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
|
// setup poll detector
|
||||||
m68k_poll.flag = P32XF_68KPOLL;
|
m68k_poll.flag = P32XF_68KPOLL;
|
||||||
m68k_poll.cyc_max = 64;
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// byteswap, data needs to be int aligned, src can match dst
|
||||||
static void Byteswap(unsigned char *data,int len)
|
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
|
m = 0x00ff00ff;
|
||||||
{
|
for (i = 0; i < len / 4; i++) {
|
||||||
unsigned short *pd=(unsigned short *)(data+i);
|
unsigned int t = ps[i];
|
||||||
int value=*pd; // Get 2 bytes
|
pd[i] = ((t & m) << 8) | ((t & ~m) >> 8);
|
||||||
|
|
||||||
value=(value<<8)|(value>>8); // Byteswap it
|
|
||||||
*pd=(unsigned short)value; // Put 2b ytes
|
|
||||||
i+=2;
|
|
||||||
}
|
}
|
||||||
while (i+2<=len);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Interleve a 16k block and byteswap
|
// 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.");
|
elprintf(EL_STATUS, "SMD format detected.");
|
||||||
DecodeSmd(rom,size); size-=0x200; // Decode and byteswap SMD
|
DecodeSmd(rom,size); size-=0x200; // Decode and byteswap SMD
|
||||||
}
|
}
|
||||||
else Byteswap(rom,size); // Just byteswap
|
else Byteswap(rom, rom, size); // Just byteswap
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -621,9 +619,9 @@ static unsigned int rom_crc32(void)
|
||||||
elprintf(EL_STATUS, "caclulating CRC32..");
|
elprintf(EL_STATUS, "caclulating CRC32..");
|
||||||
|
|
||||||
// have to unbyteswap for calculation..
|
// have to unbyteswap for calculation..
|
||||||
Byteswap(Pico.rom, Pico.romsize);
|
Byteswap(Pico.rom, Pico.rom, Pico.romsize);
|
||||||
crc = crc32(0, 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;
|
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
|
// this must switch to 32bpp mode
|
||||||
extern void emu_32x_startup(void);
|
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
|
// Pico.c
|
||||||
#define POPT_EN_FM (1<< 0) // 00 000x
|
#define POPT_EN_FM (1<< 0) // 00 000x
|
||||||
#define POPT_EN_PSG (1<< 1)
|
#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_vbr(c) (c) ? ssh2.vbr : msh2.vbr
|
||||||
#define sh2_sr(c) (c) ? ssh2.sr : msh2.sr
|
#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
|
// main oscillator clock which controls timing
|
||||||
|
@ -416,6 +421,9 @@ typedef struct
|
||||||
|
|
||||||
// 32X
|
// 32X
|
||||||
#define P32XS_FM (1<<15)
|
#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 P32XS2_ADEN (1<< 9)
|
||||||
#define P32XS_FULL (1<< 7) // DREQ FIFO full
|
#define P32XS_FULL (1<< 7) // DREQ FIFO full
|
||||||
#define P32XS_68S (1<< 2)
|
#define P32XS_68S (1<< 2)
|
||||||
|
@ -514,6 +522,7 @@ extern areaseek *areaSeek;
|
||||||
extern areaclose *areaClose;
|
extern areaclose *areaClose;
|
||||||
|
|
||||||
// cart.c
|
// cart.c
|
||||||
|
void Byteswap(void *dst, const void *src, int len);
|
||||||
extern void (*PicoCartMemSetup)(void);
|
extern void (*PicoCartMemSetup)(void);
|
||||||
extern void (*PicoCartUnloadHook)(void);
|
extern void (*PicoCartUnloadHook)(void);
|
||||||
|
|
||||||
|
@ -680,6 +689,7 @@ void Pico32xStartup(void);
|
||||||
void PicoUnload32x(void);
|
void PicoUnload32x(void);
|
||||||
void PicoFrame32x(void);
|
void PicoFrame32x(void);
|
||||||
void p32x_update_irls(void);
|
void p32x_update_irls(void);
|
||||||
|
void p32x_reset_sh2s(void);
|
||||||
|
|
||||||
// 32x/memory.c
|
// 32x/memory.c
|
||||||
struct Pico32xMem *Pico32xMem;
|
struct Pico32xMem *Pico32xMem;
|
||||||
|
|
|
@ -1299,6 +1299,19 @@ void emu_init(void)
|
||||||
char path[512];
|
char path[512];
|
||||||
int pos;
|
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 */
|
/* make dirs for saves */
|
||||||
pos = plat_get_root_dir(path, sizeof(path) - 4);
|
pos = plat_get_root_dir(path, sizeof(path) - 4);
|
||||||
mkdir_path(path, pos, "mds");
|
mkdir_path(path, pos, "mds");
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue