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:
notaz 2009-10-03 16:21:59 +00:00
parent 5fadfb1c37
commit 83ff19ec52
7 changed files with 405 additions and 150 deletions

View file

@ -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); \

View file

@ -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;
}
// allow only COMM for now
if ((a & 0x30) == 0x20) {
u8 *r8 = (u8 *)r;
r8[a ^ 1] = d;
}
return;
}
if (!(Pico32x.regs[0] & 1))
goto no_vdp;
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;
}
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;
}
// allow only COMM for now
if ((a & 0x30) == 0x20)
r[a / 2] = d;
return;
}
if (!(Pico32x.regs[0] & 1))
goto no_vdp;
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;
}
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,13 +1137,126 @@ 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))
static void get_bios(void)
{
u16 *ps;
u32 *pl;
int i;
// 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);
}
else {
// generate 68k ROM
ps = (u16 *)Pico32xMem->m68k_rom;
pl = (u32 *)ps;
for (i = 1; i < 0xc0/4; i++)
pl[i] = HWSWAP(0x880200 + (i - 1) * 6);
// fill with nops
for (i = 0xc0/2; i < 0x100/2; i++)
ps[i] = 0x4e71;
#if 0
ps[0xc0/2] = 0x46fc;
ps[0xc2/2] = 0x2700; // move #0x2700,sr
ps[0xfe/2] = 0x60fe; // jump to self
#else
ps[0xfe/2] = 0x4e75; // rts
#endif
}
// fill remaining m68k_rom page with game ROM
memcpy(Pico32xMem->m68k_rom + 0x100, Pico.rom + 0x100, sizeof(Pico32xMem->m68k_rom) - 0x100);
// 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));
}
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)
{
unsigned short *ps;
unsigned int *pl;
unsigned int rs;
int i;
Pico32xMem = calloc(1, sizeof(*Pico32xMem));
if (Pico32xMem == NULL) {
@ -1033,57 +1266,7 @@ void PicoMemSetup32x(void)
dmac0 = (void *)&Pico32xMem->sh2_peri_regs[0][0x180 / 4];
// generate 68k ROM
ps = (unsigned short *)Pico32xMem->m68k_rom;
pl = (unsigned int *)Pico32xMem->m68k_rom;
for (i = 1; i < 0xc0/4; i++)
pl[i] = HWSWAP(0x880200 + (i - 1) * 6);
// fill with nops
for (i = 0xc0/2; i < 0x100/2; i++)
ps[i] = 0x4e71;
#if 0
ps[0xc0/2] = 0x46fc;
ps[0xc2/2] = 0x2700; // move #0x2700,sr
ps[0xfe/2] = 0x60fe; // jump to self
#else
ps[0xfe/2] = 0x4e75; // rts
#endif
// fill remaining mem with 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);
}
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;
}
}
get_bios();
// cartridge area becomes unmapped
// XXX: we take the easy way and don't unmap ROM,
@ -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;

View file

@ -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;
}

View file

@ -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)

View file

@ -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;