From 4ff2d52753e46bce5622a5935f3d3750b5848f8f Mon Sep 17 00:00:00 2001 From: notaz Date: Mon, 19 Mar 2007 18:55:28 +0000 Subject: [PATCH] bugfixes, cd/Memory.s git-svn-id: file:///home/notaz/opt/svn/PicoDrive@70 be3aeb3a-fb24-0410-a615-afba39da0efa --- Pico/Draw2.s | 2 + Pico/Memory.s | 29 +- Pico/MemoryCmn.c | 10 +- Pico/PicoInt.h | 35 +- Pico/cd/Area.c | 3 + Pico/cd/Memory.c | 199 +++-- Pico/cd/Memory.s | 1827 ++++++++++++++++++++++++++++++++++++++++ Pico/cd/Pico.c | 3 + Pico/cd/cell_map.c | 2 +- platform/gp2x/940ctl.c | 10 +- platform/gp2x/Makefile | 8 + platform/gp2x/emu.c | 34 +- platform/gp2x/menu.c | 2 +- platform/readme.txt | 3 +- 14 files changed, 2043 insertions(+), 124 deletions(-) create mode 100644 Pico/cd/Memory.s diff --git a/Pico/Draw2.s b/Pico/Draw2.s index f8463cf..09c7ac7 100644 --- a/Pico/Draw2.s +++ b/Pico/Draw2.s @@ -1,3 +1,5 @@ +@ vim:filetype=armasm + @ assembly optimized versions of most funtions from draw2.c @ this is highly specialized, be careful if changing related C code! diff --git a/Pico/Memory.s b/Pico/Memory.s index 02c5a2c..8fd4e13 100644 --- a/Pico/Memory.s +++ b/Pico/Memory.s @@ -1,3 +1,5 @@ +@ vim:filetype=armasm + @ memory handlers with banking support for SSF II - The New Challengers @ mostly based on Gens code @@ -485,18 +487,20 @@ m_read16_romF: @ 0x780000 - 0x7fffff m_read16_rom 0xF m_read16_misc: - mov r1, #16 - ldr r2, =OtherRead16 bic r0, r0, #1 - bx r2 + mov r1, #16 + b OtherRead16 +@ ldr r2, =OtherRead16 +@ bx r2 m_read16_vdp: tst r0, #0x70000 tsteq r0, #0x000e0 bxne lr @ invalid read - ldr r1, =PicoVideoRead bic r0, r0, #1 - bx r1 + b PicoVideoRead +@ ldr r1, =PicoVideoRead +@ bx r1 m_read16_ram: ldr r1, =Pico @@ -506,10 +510,11 @@ m_read16_ram: bx lr m_read16_above_rom: - mov r1, #16 - ldr r2, =OtherRead16End bic r0, r0, #1 - bx r2 + mov r1, #16 + b OtherRead16End +@ ldr r2, =OtherRead16End +@ bx r2 .pool @@ -633,12 +638,10 @@ m_read32_vdp: tsteq r0, #0x000e0 bxne lr @ invalid read bic r0, r0, #1 - stmfd sp!,{r0,lr} + add r1, r0, #2 + stmfd sp!,{r1,lr} bl PicoVideoRead - mov r1, r0 - ldmfd sp!,{r0} - stmfd sp!,{r1} - add r0, r0, #2 + swp r0, r0, [sp] bl PicoVideoRead ldmfd sp!,{r1,lr} orr r0, r0, r1, lsl #16 diff --git a/Pico/MemoryCmn.c b/Pico/MemoryCmn.c index 43433af..02d45d8 100644 --- a/Pico/MemoryCmn.c +++ b/Pico/MemoryCmn.c @@ -124,7 +124,10 @@ end: //extern UINT32 mz80GetRegisterValue(void *, UINT32); -static void OtherWrite8(u32 a,u32 d,int realsize) +#ifndef _ASM_CD_MEMORY_C +static +#endif +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 @@ -187,7 +190,10 @@ static void OtherWrite8(u32 a,u32 d,int realsize) } -static void OtherWrite16(u32 a,u32 d) +#ifndef _ASM_CD_MEMORY_C +static +#endif +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) diff --git a/Pico/PicoInt.h b/Pico/PicoInt.h index 47ba2c9..694952e 100644 --- a/Pico/PicoInt.h +++ b/Pico/PicoInt.h @@ -160,11 +160,11 @@ struct Pico // sram struct PicoSRAM { - unsigned char *data; // actual data - unsigned int start; // start address in 68k address space + unsigned char *data; // actual data + unsigned int start; // start address in 68k address space unsigned int end; - unsigned char resize; // 1=SRAM size changed and needs to be reallocated on PicoReset - unsigned char reg_back; // copy of Pico.m.sram_reg to set after reset + unsigned char resize; // 0c: 1=SRAM size changed and needs to be reallocated on PicoReset + unsigned char reg_back; // copy of Pico.m.sram_reg to set after reset unsigned char changed; unsigned char pad; }; @@ -182,10 +182,10 @@ struct mcd_pcm unsigned char bank; int pad1; - struct pcm_chan + struct pcm_chan // 08, size 0x10 { unsigned char regs[8]; - unsigned int addr; // played sample address + unsigned int addr; // .08: played sample address int pad; } ch[8]; }; @@ -195,24 +195,24 @@ struct mcd_misc unsigned short hint_vector; unsigned char busreq; unsigned char s68k_pend_ints; - unsigned int state_flags; // emu state: reset_pending, + unsigned int state_flags; // 04: emu state: reset_pending, unsigned int counter75hz; - unsigned short audio_offset; // for savestates: play pointer offset (0-1023) + unsigned short audio_offset; // 0c: for savestates: play pointer offset (0-1023) unsigned char audio_track; // playing audio track # (zero based) char pad1; - int timer_int3; + int timer_int3; // 10 unsigned int timer_stopwatch; int pad[10]; }; typedef struct { - unsigned char bios[0x20000]; // 128K - union { // 512K + unsigned char bios[0x20000]; // 000000: 128K + union { // 020000: 512K unsigned char prg_ram[0x80000]; unsigned char prg_ram_b[4][0x20000]; }; - union { // 256K + union { // 0a0000: 256K struct { unsigned char word_ram2M[0x40000]; unsigned char unused[0x20000]; @@ -222,19 +222,19 @@ typedef struct unsigned char word_ram1M[2][0x20000]; }; }; - union { // 64K + union { // 100000: 64K unsigned char pcm_ram[0x10000]; unsigned char pcm_ram_b[0x10][0x1000]; }; - unsigned char bram[0x2000]; // 8K - unsigned char s68k_regs[0x200]; // GA, not CPU regs - struct mcd_pcm pcm; + unsigned char s68k_regs[0x200]; // 110000: GA, not CPU regs + unsigned char bram[0x2000]; // 110200: 8K + struct mcd_misc m; // 112200: misc + struct mcd_pcm pcm; // 112240: _scd_toc TOC; // not to be saved CDD cdd; CDC cdc; _scd scd; Rot_Comp rot_comp; - struct mcd_misc m; } mcd_state; #define Pico_mcd ((mcd_state *)Pico.rom) @@ -268,6 +268,7 @@ void z80_write16(unsigned short data, unsigned short a); // cd/Memory.c void PicoMemSetupCD(void); +void PicoMemResetCD(int r3); unsigned char PicoReadCD8 (unsigned int a); unsigned short PicoReadCD16(unsigned int a); unsigned int PicoReadCD32(unsigned int a); diff --git a/Pico/cd/Area.c b/Pico/cd/Area.c index bfc1ffa..bd8d157 100644 --- a/Pico/cd/Area.c +++ b/Pico/cd/Area.c @@ -243,6 +243,9 @@ int PicoCdLoadState(void *file) /* after load events */ if (Pico_mcd->s68k_regs[3]&4) // 1M mode? wram_2M_to_1M(Pico_mcd->word_ram2M); +#ifdef _ASM_CD_MEMORY_C + PicoMemResetCD(Pico_mcd->s68k_regs[3]); +#endif if (Pico_mcd->m.audio_track > 0 && Pico_mcd->m.audio_track < Pico_mcd->TOC.Last_Track) mp3_start_play(Pico_mcd->TOC.Tracks[Pico_mcd->m.audio_track].F, Pico_mcd->m.audio_offset); // restore hint vector diff --git a/Pico/cd/Memory.c b/Pico/cd/Memory.c index 805c9f3..ce23433 100644 --- a/Pico/cd/Memory.c +++ b/Pico/cd/Memory.c @@ -19,8 +19,6 @@ #include "gfx_cd.h" #include "pcm.h" -#include "cell_map.c" - typedef unsigned char u8; typedef unsigned short u16; typedef unsigned int u32; @@ -36,6 +34,13 @@ typedef unsigned int u32; // ----------------------------------------------------------------- +#ifndef _ASM_CD_MEMORY_C +void PicoMemResetCD(int r3) +{ +} +#endif + +#ifndef _ASM_CD_MEMORY_C static u32 m68k_reg_read16(u32 a) { u32 d=0; @@ -63,8 +68,8 @@ static u32 m68k_reg_read16(u32 a) dprintf("m68k FIXME: reserved read"); goto end; case 0xC: - dprintf("m68k stopwatch timer read"); d = Pico_mcd->m.timer_stopwatch >> 16; + dprintf("m68k stopwatch timer read (%04x)", d); goto end; } @@ -81,8 +86,12 @@ end: // dprintf("ret = %04x", d); return d; } +#endif -static void m68k_reg_write8(u32 a, u32 d) +#ifndef _ASM_CD_MEMORY_C +static +#endif +void m68k_reg_write8(u32 a, u32 d) { a &= 0x3f; // dprintf("m68k_regs w%2i: [%02x] %02x @%06x", realsize, a, d, SekPc); @@ -99,8 +108,8 @@ static void m68k_reg_write8(u32 a, u32 d) if ( (Pico_mcd->m.busreq&2) != (d&2)) dprintf("m68k: s68k brq %i", (d&2)>>1); if ((Pico_mcd->m.state_flags&1) && (d&3)==1) { SekResetS68k(); // S68k comes out of RESET or BRQ state - Pico_mcd->m.state_flags&=~1; - dprintf("m68k: resetting s68k, cycles=%i", SekCyclesLeft); + Pico_mcd->m.state_flags&=~1; + dprintf("m68k: resetting s68k, cycles=%i", SekCyclesLeft); } Pico_mcd->m.busreq = d; return; @@ -164,7 +173,10 @@ static void m68k_reg_write8(u32 a, u32 d) } -static u32 s68k_reg_read16(u32 a) +#ifndef _ASM_CD_MEMORY_C +static +#endif +u32 s68k_reg_read16(u32 a) { u32 d=0; @@ -176,7 +188,7 @@ static u32 s68k_reg_read16(u32 a) goto end; case 2: d = (Pico_mcd->s68k_regs[a]<<8) | (Pico_mcd->s68k_regs[a+1]&0x1f); - dprintf("s68k_regs r3: %02x @%06x", (u8)d, SekPc); + dprintf("s68k_regs r3: %02x @%06x", (u8)d, SekPcS68k); goto end; case 6: d = CDC_Read_Reg(); @@ -185,11 +197,11 @@ static u32 s68k_reg_read16(u32 a) d = Read_CDC_Host(1); // Gens returns 0 here on byte reads goto end; case 0xC: - dprintf("s68k stopwatch timer read"); d = Pico_mcd->m.timer_stopwatch >> 16; + dprintf("s68k stopwatch timer read (%04x)", d); goto end; case 0x30: - dprintf("s68k int3 timer read"); + dprintf("s68k int3 timer read (%02x%02x)", Pico_mcd->s68k_regs[30], Pico_mcd->s68k_regs[31]); break; case 0x34: // fader d = 0; // no busy bit @@ -217,7 +229,10 @@ end: return d; } -static void s68k_reg_write8(u32 a, u32 d) +#ifndef _ASM_CD_MEMORY_C +static +#endif +void s68k_reg_write8(u32 a, u32 d) { //dprintf("s68k_regs w%2i: [%02x] %02x @ %06x", realsize, a, d, SekPcS68k); @@ -229,20 +244,33 @@ static void s68k_reg_write8(u32 a, u32 d) int dold = Pico_mcd->s68k_regs[3]; dprintf("s68k_regs w3: %02x @%06x", (u8)d, SekPc); d &= 0x1d; + d |= dold&0xc2; if (d&4) { - d |= dold&0xc2; - if ((d ^ dold) & 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 +#ifdef _ASM_CD_MEMORY_C + PicoMemResetCD(d); +#endif + } if (!(dold & 4)) { dprintf("wram mode 2M->1M"); wram_2M_to_1M(Pico_mcd->word_ram2M); - } + } } else { - d |= Pico_mcd->s68k_regs[3]&0xc3; - if (d&1) d &= ~2; // return word RAM to m68k in 2M mode if (dold & 4) { dprintf("wram mode 1M->2M"); + if (!(d&1)) { // it didn't set the ret bit, which means it doesn't want to give WRAM to m68k + d &= ~3; + d |= (dold&1) ? 2 : 1; // then give it to the one which had bank0 in 1M mode + } wram_1M_to_2M(Pico_mcd->word_ram2M); - } +#ifdef _ASM_CD_MEMORY_C + PicoMemResetCD(d); +#endif + } + else + d |= dold&1; + if (d&1) d &= ~2; // return word RAM to m68k in 2M mode } break; } @@ -307,7 +335,7 @@ static void s68k_reg_write8(u32 a, u32 d) } - +#ifndef _ASM_CD_MEMORY_C static u32 OtherRead16End(u32 a, int realsize) { u32 d=0; @@ -334,12 +362,17 @@ static void OtherWrite8End(u32 a, u32 d, int realsize) #undef _ASM_MEMORY_C #include "../MemoryCmn.c" - +#include "cell_map.c" +#endif // !def _ASM_CD_MEMORY_C // ----------------------------------------------------------------- // Read Rom and read Ram -u8 PicoReadM68k8(u32 a) +//u8 PicoReadM68k8_(u32 a); +#ifdef _ASM_CD_MEMORY_C +u8 PicoReadM68k8(u32 a); +#else +static u8 PicoReadM68k8(u32 a) { u32 d=0; @@ -350,28 +383,12 @@ u8 PicoReadM68k8(u32 a) if (a < 0x20000) { d = *(u8 *)(Pico_mcd->bios+(a^1)); goto end; } // bios // prg RAM - if ((a&0xfe0000)==0x020000) { + if ((a&0xfe0000)==0x020000 && (Pico_mcd->m.busreq&2)) { u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6]; d = *(prg_bank+((a^1)&0x1ffff)); goto end; } -#if 0 - if (a == 0x200000 && SekPc == 0xff0b66 && Pico.m.frame_count > 1000) - { - int i; - FILE *ff; - unsigned short *ram = (unsigned short *) Pico.ram; - // unswap and dump RAM - for (i = 0; i < 0x10000/2; i++) - ram[i] = (ram[i]>>8) | (ram[i]<<8); - ff = fopen("ram.bin", "wb"); - fwrite(ram, 1, 0x10000, ff); - fclose(ff); - exit(0); - } -#endif - // word RAM if ((a&0xfc0000)==0x200000) { wrdprintf("m68k_wram r8: [%06x] @%06x", a, SekPc); @@ -406,9 +423,13 @@ u8 PicoReadM68k8(u32 a) #endif return (u8)d; } +#endif -u16 PicoReadM68k16(u32 a) +#ifdef _ASM_CD_MEMORY_C +u16 PicoReadM68k16(u32 a); +#else +static u16 PicoReadM68k16(u32 a) { u16 d=0; @@ -419,7 +440,7 @@ u16 PicoReadM68k16(u32 a) if (a < 0x20000) { d = *(u16 *)(Pico_mcd->bios+a); goto end; } // bios // prg RAM - if ((a&0xfe0000)==0x020000) { + if ((a&0xfe0000)==0x020000 && (Pico_mcd->m.busreq&2)) { u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6]; d = *(u16 *)(prg_bank+(a&0x1fffe)); goto end; @@ -457,9 +478,13 @@ u16 PicoReadM68k16(u32 a) #endif return d; } +#endif -u32 PicoReadM68k32(u32 a) +#ifdef _ASM_CD_MEMORY_C +u32 PicoReadM68k32(u32 a); +#else +static u32 PicoReadM68k32(u32 a) { u32 d=0; @@ -470,7 +495,7 @@ u32 PicoReadM68k32(u32 a) if (a < 0x20000) { u16 *pm=(u16 *)(Pico_mcd->bios+a); d = (pm[0]<<16)|pm[1]; goto end; } // bios // prg RAM - if ((a&0xfe0000)==0x020000) { + if ((a&0xfe0000)==0x020000 && (Pico_mcd->m.busreq&2)) { u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6]; u16 *pm=(u16 *)(prg_bank+(a&0x1fffe)); d = (pm[0]<<16)|pm[1]; @@ -485,10 +510,10 @@ u32 PicoReadM68k32(u32 a) 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); + 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 { u16 *pm=(u16 *)(Pico_mcd->word_ram1M[bank]+(a&0x1fffe)); d = (pm[0]<<16)|pm[1]; } @@ -514,12 +539,16 @@ u32 PicoReadM68k32(u32 a) #endif return d; } +#endif // ----------------------------------------------------------------- // Write Ram -void PicoWriteM68k8(u32 a,u8 d) +#ifdef _ASM_CD_MEMORY_C +void PicoWriteM68k8(u32 a,u8 d); +#else +static void PicoWriteM68k8(u32 a,u8 d) { #ifdef __debug_io dprintf("w8 : %06x, %02x @%06x", a&0xffffff, d, SekPc); @@ -536,7 +565,7 @@ void PicoWriteM68k8(u32 a,u8 d) a&=0xffffff; // prg RAM - if ((a&0xfe0000)==0x020000) { + if ((a&0xfe0000)==0x020000 && (Pico_mcd->m.busreq&2)) { u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6]; *(u8 *)(prg_bank+((a^1)&0x1ffff))=d; return; @@ -563,9 +592,13 @@ void PicoWriteM68k8(u32 a,u8 d) OtherWrite8(a,d,8); } +#endif -void PicoWriteM68k16(u32 a,u16 d) +#ifdef _ASM_CD_MEMORY_C +void PicoWriteM68k16(u32 a,u16 d); +#else +static void PicoWriteM68k16(u32 a,u16 d) { #ifdef __debug_io dprintf("w16: %06x, %04x", a&0xffffff, d); @@ -580,7 +613,7 @@ void PicoWriteM68k16(u32 a,u16 d) a&=0xfffffe; // prg RAM - if ((a&0xfe0000)==0x020000) { + if ((a&0xfe0000)==0x020000 && (Pico_mcd->m.busreq&2)) { u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6]; *(u16 *)(prg_bank+(a&0x1fffe))=d; return; @@ -607,9 +640,13 @@ void PicoWriteM68k16(u32 a,u16 d) OtherWrite16(a,d); } +#endif -void PicoWriteM68k32(u32 a,u32 d) +#ifdef _ASM_CD_MEMORY_C +void PicoWriteM68k32(u32 a,u32 d); +#else +static void PicoWriteM68k32(u32 a,u32 d) { #ifdef __debug_io dprintf("w32: %06x, %08x", a&0xffffff, d); @@ -626,7 +663,7 @@ void PicoWriteM68k32(u32 a,u32 d) a&=0xfffffe; // prg RAM - if ((a&0xfe0000)==0x020000) { + if ((a&0xfe0000)==0x020000 && (Pico_mcd->m.busreq&2)) { u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6]; u16 *pm=(u16 *)(prg_bank+(a&0x1fffe)); pm[0]=(u16)(d>>16); pm[1]=(u16)d; @@ -642,10 +679,10 @@ void PicoWriteM68k32(u32 a,u32 d) 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; + 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 { u16 *pm=(u16 *)(Pico_mcd->word_ram1M[bank]+(a&0x1fffe)); pm[0]=(u16)(d>>16); pm[1]=(u16)d; @@ -664,12 +701,15 @@ void PicoWriteM68k32(u32 a,u32 d) OtherWrite16(a, (u16)(d>>16)); OtherWrite16(a+2,(u16)d); } +#endif // ----------------------------------------------------------------- - -u8 PicoReadS68k8(u32 a) +#ifdef _ASM_CD_MEMORY_C +u8 PicoReadS68k8(u32 a); +#else +static u8 PicoReadS68k8(u32 a) { u32 d=0; @@ -753,9 +793,14 @@ u8 PicoReadS68k8(u32 a) #endif return (u8)d; } +#endif -u16 PicoReadS68k16(u32 a) +//u16 PicoReadS68k16_(u32 a); +#ifdef _ASM_CD_MEMORY_C +u16 PicoReadS68k16(u32 a); +#else +static u16 PicoReadS68k16(u32 a) { u32 d=0; @@ -808,17 +853,17 @@ u16 PicoReadS68k16(u32 a) // bram if ((a&0xff0000)==0xfe0000) { - dprintf("s68k_bram r16: [%06x] @%06x", a, SekPcS68k); + dprintf("FIXME: s68k_bram r16: [%06x] @%06x", a, SekPcS68k); a = (a>>1)&0x1fff; d = Pico_mcd->bram[a++]; // Gens does little endian here, and so do we.. - d|= Pico_mcd->bram[a++] << 8; + d|= Pico_mcd->bram[a++] << 8; // This is most likely wrong dprintf("ret = %04x", d); goto end; } // PCM if ((a&0xff8000)==0xff0000) { - dprintf("s68k_pcm r16: [%06x] @%06x", a, SekPcS68k); + dprintf("FIXME: s68k_pcm r16: [%06x] @%06x", a, SekPcS68k); a &= 0x7fff; if (a >= 0x2000) d = Pico_mcd->pcm_ram_b[Pico_mcd->pcm.bank][(a>>1)&0xfff]; @@ -840,9 +885,13 @@ u16 PicoReadS68k16(u32 a) #endif return d; } +#endif -u32 PicoReadS68k32(u32 a) +#ifdef _ASM_CD_MEMORY_C +u32 PicoReadS68k32(u32 a); +#else +static u32 PicoReadS68k32(u32 a) { u32 d=0; @@ -898,7 +947,7 @@ u32 PicoReadS68k32(u32 a) // PCM if ((a&0xff8000)==0xff0000) { - dprintf("s68k_pcm r32: [%06x] @%06x", a, SekPcS68k); + dprintf("FIXME: s68k_pcm r32: [%06x] @%06x", a, SekPcS68k); a &= 0x7fff; if (a >= 0x2000) { a >>= 1; @@ -921,7 +970,7 @@ u32 PicoReadS68k32(u32 a) // bram if ((a&0xff0000)==0xfe0000) { - dprintf("s68k_bram r32: [%06x] @%06x", a, SekPcS68k); + dprintf("FIXME: s68k_bram r32: [%06x] @%06x", a, SekPcS68k); a = (a>>1)&0x1fff; d = Pico_mcd->bram[a++] << 16; // middle endian? TODO: verify against Fusion.. d|= Pico_mcd->bram[a++] << 24; @@ -940,6 +989,7 @@ u32 PicoReadS68k32(u32 a) #endif return d; } +#endif /* check: jaguar xj 220 (draws entire world using decode) */ @@ -998,7 +1048,10 @@ static void decode_write16(u32 a, u16 d, int r3) // ----------------------------------------------------------------- -void PicoWriteS68k8(u32 a,u8 d) +#ifdef _ASM_CD_MEMORY_C +void PicoWriteS68k8(u32 a,u8 d); +#else +static void PicoWriteS68k8(u32 a,u8 d) { #ifdef __debug_io2 dprintf("s68k w8 : %06x, %02x @%06x", a&0xffffff, d, SekPcS68k); @@ -1068,9 +1121,13 @@ void PicoWriteS68k8(u32 a,u8 d) dprintf("s68k w8 : %06x, %02x @%06x", a&0xffffff, d, SekPcS68k); } +#endif -void PicoWriteS68k16(u32 a,u16 d) +#ifdef _ASM_CD_MEMORY_C +void PicoWriteS68k16(u32 a,u16 d); +#else +static void PicoWriteS68k16(u32 a,u16 d) { #ifdef __debug_io2 dprintf("s68k w16: %06x, %04x @%06x", a&0xffffff, d, SekPcS68k); @@ -1093,7 +1150,7 @@ void PicoWriteS68k16(u32 a,u16 d) else { if (a == 0xe) { // special case, 2 byte writes would be handled differently Pico_mcd->s68k_regs[0xf] = d; - return; + return; } s68k_reg_write8(a, d>>8); s68k_reg_write8(a+1,d&0xff); @@ -1148,9 +1205,13 @@ void PicoWriteS68k16(u32 a,u16 d) dprintf("s68k w16: %06x, %04x @%06x", a&0xffffff, d, SekPcS68k); } +#endif -void PicoWriteS68k32(u32 a,u32 d) +#ifdef _ASM_CD_MEMORY_C +void PicoWriteS68k32(u32 a,u32 d); +#else +static void PicoWriteS68k32(u32 a,u32 d) { #ifdef __debug_io2 dprintf("s68k w32: %06x, %08x @%06x", a&0xffffff, d, SekPcS68k); @@ -1239,7 +1300,7 @@ void PicoWriteS68k32(u32 a,u32 d) dprintf("s68k w32: %06x, %08x @%06x", a&0xffffff, d, SekPcS68k); } - +#endif // ----------------------------------------------------------------- diff --git a/Pico/cd/Memory.s b/Pico/cd/Memory.s new file mode 100644 index 0000000..155eb72 --- /dev/null +++ b/Pico/cd/Memory.s @@ -0,0 +1,1827 @@ +@ vim:filetype=armasm + +@ Memory i/o handlers for Sega/Mega CD emulation +@ (c) Copyright 2007, Grazvydas "notaz" Ignotas +@ All Rights Reserved + + + +.equiv PCM_STEP_SHIFT, 11 + +@ jump tables +.data +.align 4 + +.altmacro +.macro mk_m68k_jump_table on sz @ operation name, size + .long m_m68k_&\on&\sz&_bios @ 0x000000 - 0x01ffff + .long m_m68k_&\on&\sz&_prgbank @ 0x020000 - 0x03ffff + .long m_&\on&_null, m_&\on&_null @ 0x040000 - 0x07ffff + .long m_&\on&_null, m_&\on&_null, m_&\on&_null, m_&\on&_null @ 0x080000 - 0x0fffff + .long m_&\on&_null, m_&\on&_null, m_&\on&_null, m_&\on&_null @ 0x100000 - 0x17ffff + .long m_&\on&_null, m_&\on&_null, m_&\on&_null, m_&\on&_null @ 0x180000 - 0x1fffff + .long m_m68k_&\on&\sz&_wordram0_2M @ 0x200000 - 0x21ffff + .long m_m68k_&\on&\sz&_wordram1_2M @ 0x220000 - 0x23ffff + .long m_&\on&_null, m_&\on&_null @ 0x240000 - 0x27ffff + .long m_&\on&_null, m_&\on&_null, m_&\on&_null, m_&\on&_null @ 0x280000 - 0x2fffff + .long m_&\on&_null, m_&\on&_null, m_&\on&_null, m_&\on&_null @ 0x300000 + .long m_&\on&_null, m_&\on&_null, m_&\on&_null, m_&\on&_null @ - 0x3fffff + .long m_&\on&_null, m_&\on&_null, m_&\on&_null, m_&\on&_null @ 0x400000 + .long m_&\on&_null, m_&\on&_null, m_&\on&_null, m_&\on&_null @ - 0x4fffff + .long m_&\on&_null, m_&\on&_null, m_&\on&_null, m_&\on&_null @ 0x500000 + .long m_&\on&_null, m_&\on&_null, m_&\on&_null, m_&\on&_null @ - 0x5fffff + .long m_&\on&_null, m_&\on&_null, m_&\on&_null, m_&\on&_null @ 0x600000 + .long m_&\on&_null, m_&\on&_null, m_&\on&_null, m_&\on&_null @ - 0x6fffff + .long m_&\on&_null, m_&\on&_null, m_&\on&_null, m_&\on&_null @ 0x700000 + .long m_&\on&_null, m_&\on&_null, m_&\on&_null, m_&\on&_null @ - 0x7fffff + .long m_&\on&_null, m_&\on&_null, m_&\on&_null, m_&\on&_null @ 0x800000 + .long m_&\on&_null, m_&\on&_null, m_&\on&_null, m_&\on&_null @ - 0x8fffff + .long m_&\on&_null, m_&\on&_null, m_&\on&_null, m_&\on&_null @ 0x900000 + .long m_&\on&_null, m_&\on&_null, m_&\on&_null, m_&\on&_null @ - 0x9fffff + .long m_m68k_&\on&\sz&_system_io @ 0xa00000 - 0xa1ffff + .long m_&\on&_null, m_&\on&_null, m_&\on&_null @ 0xa20000 - 0xa7ffff + .long m_&\on&_null, m_&\on&_null, m_&\on&_null, m_&\on&_null @ 0xa80000 - 0xafffff + .long m_&\on&_null, m_&\on&_null, m_&\on&_null, m_&\on&_null @ 0xb00000 + .long m_&\on&_null, m_&\on&_null, m_&\on&_null, m_&\on&_null @ - 0xbfffff + .long m_m68k_&\on&\sz&_vdp, m_m68k_&\on&\sz&_vdp, m_m68k_&\on&\sz&_vdp, m_m68k_&\on&\sz&_vdp @ 0xc00000 + .long m_m68k_&\on&\sz&_vdp, m_m68k_&\on&\sz&_vdp, m_m68k_&\on&\sz&_vdp, m_m68k_&\on&\sz&_vdp @ - 0xcfffff + .long m_&\on&_null, m_&\on&_null, m_&\on&_null, m_&\on&_null @ 0xd00000 + .long m_&\on&_null, m_&\on&_null, m_&\on&_null, m_&\on&_null @ - 0xdfffff + .long m_m68k_&\on&\sz&_ram, m_m68k_&\on&\sz&_ram, m_m68k_&\on&\sz&_ram, m_m68k_&\on&\sz&_ram @ 0xe00000 + .long m_m68k_&\on&\sz&_ram, m_m68k_&\on&\sz&_ram, m_m68k_&\on&\sz&_ram, m_m68k_&\on&\sz&_ram @ - 0xefffff + .long m_m68k_&\on&\sz&_ram, m_m68k_&\on&\sz&_ram, m_m68k_&\on&\sz&_ram, m_m68k_&\on&\sz&_ram @ 0xf00000 + .long m_m68k_&\on&\sz&_ram, m_m68k_&\on&\sz&_ram, m_m68k_&\on&\sz&_ram, m_m68k_&\on&\sz&_ram @ - 0xffffff +.endm + +.macro mk_s68k_jump_table1 on sz @ operation name, size + .long m_s68k_&\on&\sz&_prg, m_s68k_&\on&\sz&_prg, m_s68k_&\on&\sz&_prg, m_s68k_&\on&\sz&_prg @ 0x000000 - 0x07ffff + .long m_s68k_&\on&\sz&_wordram_2M @ 0x080000 - 0x09ffff + .long m_s68k_&\on&\sz&_wordram_2M @ 0x0a0000 - 0x0bffff + .long m_&\on&_null @ 0x0c0000 - 0x0dffff, 1M area + .long m_&\on&_null @ 0x0e0000 - 0x0fffff +.endm + +.macro mk_s68k_jump_table2 on sz @ operation name, size + .long m_s68k_&\on&\sz&_backup @ 0xfe0000 - 0xfe7fff + .long m_s68k_&\on&\sz&_backup @ 0xfe8000 - 0xfeffff + .long m_s68k_&\on&\sz&_pcm @ 0xff0000 - 0xff7fff + .long m_s68k_&\on&\sz&_regs @ 0xff8000 - 0xffffff +.endm + + +@ the jumptables themselves +m_m68k_read8_table: mk_m68k_jump_table read 8 +m_m68k_read16_table: mk_m68k_jump_table read 16 +m_m68k_read32_table: mk_m68k_jump_table read 32 +m_m68k_write8_table: mk_m68k_jump_table write 8 +m_m68k_write16_table: mk_m68k_jump_table write 16 +m_m68k_write32_table: mk_m68k_jump_table write 32 + + +m_s68k_read8_table: + mk_s68k_jump_table1 read 8 + mk_s68k_jump_table2 read 8 +m_s68k_read16_table: + mk_s68k_jump_table1 read 16 + mk_s68k_jump_table2 read 16 +m_s68k_read32_table: + mk_s68k_jump_table1 read 32 + mk_s68k_jump_table2 read 32 +m_s68k_write8_table: + mk_s68k_jump_table1 write 8 + mk_s68k_jump_table2 write 8 +m_s68k_write16_table: + mk_s68k_jump_table1 write 16 + mk_s68k_jump_table2 write 16 +m_s68k_write32_table: + mk_s68k_jump_table1 write 32 + mk_s68k_jump_table2 write 32 + + +@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + +.text +.align 4 + +.global PicoMemResetCD +.global PicoReadM68k8 +.global PicoReadM68k16 +.global PicoReadM68k32 +.global PicoWriteM68k8 +.global PicoWriteM68k16 +.global PicoWriteM68k32 +.global PicoReadS68k8 +.global PicoReadS68k16 +.global PicoReadS68k32 +.global PicoWriteS68k8 +.global PicoWriteS68k16 +.global PicoWriteS68k32 + +@ externs, just for reference +.extern Pico +.extern z80Read8 +.extern OtherRead16 +.extern PicoVideoRead +.extern Read_CDC_Host +.extern m68k_reg_write8 +.extern OtherWrite8 +.extern OtherWrite16 +.extern gfx_cd_read +.extern s68k_reg_read16 +.extern SRam +.extern gfx_cd_write +.extern s68k_reg_write8 + + +@ r0=reg3, r1-r3=temp +.macro mk_update_table on sz @ operation name, size + @ we only set word-ram handlers + ldr r1, =m_m68k_&\on&\sz&_table + ldr r12,=m_s68k_&\on&\sz&_table + tst r0, #4 + bne 0f @ pmr_8_1M + +@ pmr_8_2M: + ldr r2, =m_m68k_&\on&\sz&_wordram0_2M + ldr r3, =m_s68k_&\on&\sz&_wordram_2M + str r2, [r1, #16*4] + str r2, [r1, #17*4] + ldr r2, =m_&\on&_null + str r3, [r12,#4*4] + str r3, [r12,#5*4] + str r2, [r12,#6*4] + b 9f @ pmr_8_done + +0: @ pmr_8_1M: + tst r0, #1 + bne 1f @ pmr_8_1M1 + +@ pmr_8_1M0: + ldr r2, =m_m68k_&\on&\sz&_wordram0_1M_b0 + ldr r3, =m_m68k_&\on&\sz&_wordram1_1M_b0 + str r2, [r1, #16*4] + str r3, [r1, #17*4] + ldr r2, =m_s68k_&\on&\sz&_wordram_2M_decode_b1 + ldr r3, =m_s68k_&\on&\sz&_wordram_1M_b1 + str r2, [r12,#4*4] + str r2, [r12,#5*4] + str r3, [r12,#6*4] + b 9f @ pmr_8_done + +1: @ pmr_8_1M1: + ldr r2, =m_m68k_&\on&\sz&_wordram0_1M_b1 + ldr r3, =m_m68k_&\on&\sz&_wordram1_1M_b1 + str r2, [r1, #16*4] + str r3, [r1, #17*4] + ldr r2, =m_s68k_&\on&\sz&_wordram_2M_decode_b0 + ldr r3, =m_s68k_&\on&\sz&_wordram_1M_b0 + str r2, [r12,#4*4] + str r2, [r12,#5*4] + str r3, [r12,#6*4] + +9: @ pmr_8_done: +.endm + + +PicoMemResetCD: @ r3 + mk_update_table read 8 + mk_update_table read 16 + mk_update_table read 32 + mk_update_table write 8 + mk_update_table write 16 + mk_update_table write 32 + bx lr + + +.pool + +@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + +.macro mk_entry_m68k table + ldr r2, =\table + bic r0, r0, #0xff000000 + and r3, r0, #0x00fe0000 + ldr pc, [r2, r3, lsr #15] +.endm + +PicoReadM68k8: @ u32 a + mk_entry_m68k m_m68k_read8_table + +PicoReadM68k16: @ u32 a + mk_entry_m68k m_m68k_read16_table + +PicoReadM68k32: @ u32 a + mk_entry_m68k m_m68k_read32_table + +PicoWriteM68k8: @ u32 a, u8 d + mk_entry_m68k m_m68k_write8_table + +PicoWriteM68k16: @ u32 a, u16 d + mk_entry_m68k m_m68k_write16_table + +PicoWriteM68k32: @ u32 a, u32 d + mk_entry_m68k m_m68k_write32_table + + +.macro mk_entry_s68k table + ldr r2, =\table + bic r0, r0, #0xff000000 + and r3, r0, #0x00fe0000 + cmp r3, #0x000e0000 + ldrlt pc, [r2, r3, lsr #15] + add r2, r2, #8*4 @ skip to table2 + cmp r3, #0x00fe0000 + andge r3, r0, #0x00018000 + ldrge pc, [r2, r3, lsr #13] + mov r0, #0 + bx lr +.endm + +PicoReadS68k8: @ u32 a + mk_entry_s68k m_s68k_read8_table + +PicoReadS68k16: @ u32 a + mk_entry_s68k m_s68k_read16_table + +PicoReadS68k32: @ u32 a + mk_entry_s68k m_s68k_read32_table + +PicoWriteS68k8: @ u32 a, u8 d + mk_entry_s68k m_s68k_write8_table + +PicoWriteS68k16: @ u32 a, u16 d + mk_entry_s68k m_s68k_write16_table + +PicoWriteS68k32: @ u32 a, u32 d + mk_entry_s68k m_s68k_write32_table + + +.pool + +@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + +@ utilities + +@ r0=addr[in,out], r1,r2=tmp +.macro cell_map + ands r1, r0, #0x01c000 + ldrne pc, [pc, r1, lsr #12] + beq 0f @ most common? + .long 0f + .long 0f + .long 0f + .long 0f + .long 1f + .long 1f + .long 2f + .long 3f +1: @ x16 cells + and r1, r0, #0x7e00 @ col + and r2, r0, #0x01fc @ row + orr r2, r2, #0x0400 + orr r1, r2, r1, ror #13 + b 9f +2: @ x8 cells + and r1, r0, #0x3f00 @ col + and r2, r0, #0x00fc @ row + orr r2, r2, #0x0600 + orr r1, r2, r1, ror #12 + b 9f +3: @ x4 cells + and r1, r0, #0x1f80 @ col + and r2, r0, #0x007c @ row + orr r1, r2, r1, ror #11 + and r2, r0,#0x1e000 + orr r1, r1, r2, lsr #6 + b 9f +0: @ x32 cells + and r1, r0, #0xfc00 @ col + and r2, r0, #0x03fc @ row + orr r1, r2, r1, ror #14 +9: + and r0, r0, #3 + orr r0, r0, r1, ror #26 @ rol 4+2 +.endm + + +@ r0=prt1, r1=ptr2 +.macro m_read32_gen + tst r0, #2 + ldrneh r0, [r1, r0]! + ldrneh r1, [r1, #2] + ldreq r0, [r1, r0] + moveq r0, r0, ror #16 + orrne r0, r1, r0, lsl #16 +.endm + + +@ r0=prt1, r1=data, r2=ptr2 +.macro m_write32_gen + tst r0, #2 + mov r1, r1, ror #16 + strneh r1, [r2, r0]! + movne r1, r1, lsr #16 + strneh r1, [r2, #2] + streq r1, [r2, r0] +.endm + + +@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + + +m_read_null: + mov r0, #0 + bx lr + + +m_m68k_read8_bios: + ldr r1, =(Pico+0x22200) + bic r0, r0, #0xfe0000 + ldr r1, [r1] + eor r0, r0, #1 + ldrb r0, [r1, r0] + bx lr + + +m_m68k_read8_prgbank: + ldr r1, =(Pico+0x22200) + eor r0, r0, #1 + ldr r1, [r1] + mov r2, #0x110000 + orr r3, r2, #0x002200 + ldr r3, [r1, r3] + ldr r2, [r1, r2] + tst r3, #0x00020000 @ have bus? + moveq r0, #0 + bxeq lr + and r2, r2, #0xc0000000 @ r3 & 0xC0 + add r1, r1, r2, lsr #12 + ldrb r0, [r1, r0] + bx lr + + +m_m68k_read8_wordram0_2M: @ 0x200000 - 0x21ffff +m_m68k_read8_wordram1_2M: @ 0x220000 - 0x23ffff + ldr r1, =(Pico+0x22200) + sub r0, r0, #0x160000 @ map to our offset, which is 0x0a0000 + ldr r1, [r1] + eor r0, r0, #1 + ldrb r0, [r1, r0] + bx lr + + +m_m68k_read8_wordram0_1M_b0: @ 0x200000 - 0x21ffff + ldr r1, =(Pico+0x22200) + sub r0, r0, #0x140000 @ map to our offset, which is 0x0c0000 + ldr r1, [r1] + eor r0, r0, #1 + ldrb r0, [r1, r0] + bx lr + + +m_m68k_read8_wordram0_1M_b1: @ 0x200000 - 0x21ffff + ldr r1, =(Pico+0x22200) + sub r0, r0, #0x120000 @ map to our offset, which is 0x0e0000 + ldr r1, [r1] + eor r0, r0, #1 + ldrb r0, [r1, r0] + bx lr + + +m_m68k_read8_wordram1_1M_b0: @ 0x220000 - 0x23ffff, cell arranged + cell_map + ldr r1, =(Pico+0x22200) + add r0, r0, #0x0c0000 + ldr r1, [r1] + eor r0, r0, #1 + ldrb r0, [r1, r0] + bx lr + + +m_m68k_read8_wordram1_1M_b1: @ 0x220000 - 0x23ffff, cell arranged + cell_map + ldr r1, =(Pico+0x22200) + add r0, r0, #0x0e0000 + ldr r1, [r1] + eor r0, r0, #1 + ldrb r0, [r1, r0] + bx lr + + +m_m68k_read8_system_io: + bic r2, r0, #0xfe0000 + bic r2, r2, #0x3f + cmp r2, #0x012000 + bne m_m68k_read8_misc + + ldr r1, =(Pico+0x22200) + and r0, r0, #0x3f + ldr r1, [r1] @ Pico.mcd (used everywhere) + cmp r0, #0x0e + ldrlt pc, [pc, r0, lsl #2] + b m_m68k_read8_hi + .long m_m68k_read8_r00 + .long m_m68k_read8_r01 + .long m_m68k_read8_r02 + .long m_m68k_read8_r03 + .long m_m68k_read8_r04 + .long m_read_null @ unused bits + .long m_m68k_read8_r06 + .long m_m68k_read8_r07 + .long m_m68k_read8_r08 + .long m_m68k_read8_r09 + .long m_read_null @ reserved + .long m_read_null + .long m_m68k_read8_r0c + .long m_m68k_read8_r0d +m_m68k_read8_r00: + add r1, r1, #0x110000 + ldr r0, [r1, #30] + and r0, r0, #0x04000000 @ we need irq2 mask state + mov r0, r0, lsr #19 + bx lr +m_m68k_read8_r01: + add r1, r1, #0x110000 + add r1, r1, #0x002200 + ldrb r0, [r1, #2] @ Pico_mcd->m.busreq + bx lr +m_m68k_read8_r02: + add r1, r1, #0x110000 + ldrb r0, [r1, #2] + bx lr +m_m68k_read8_r03: + add r1, r1, #0x110000 + ldrb r0, [r1, #3] + and r0, r0, #0xc7 + bx lr +m_m68k_read8_r04: + add r1, r1, #0x110000 + ldrb r0, [r1, #4] + bx lr +m_m68k_read8_r06: + ldrb r0, [r1, #0x73] @ IRQ vector + bx lr +m_m68k_read8_r07: + ldrb r0, [r1, #0x72] + bx lr +m_m68k_read8_r08: + mov r0, #0 + bl Read_CDC_Host @ TODO: make it local + mov r0, r0, lsr #8 + bx lr +m_m68k_read8_r09: + mov r0, #0 + b Read_CDC_Host +m_m68k_read8_r0c: + add r1, r1, #0x110000 + add r1, r1, #0x002200 + ldr r0, [r1, #0x14] @ Pico_mcd->m.timer_stopwatch + mov r0, r0, lsr #24 + bx lr +m_m68k_read8_r0d: + add r1, r1, #0x110000 + add r1, r1, #0x002200 + ldr r0, [r1, #0x14] + mov r0, r0, lsr #16 + bx lr +m_m68k_read8_hi: + cmp r0, #0x30 + movge r0, #0 + bxeq lr + add r1, r1, #0x110000 + ldrb r0, [r1, r0] + bx lr + + +m_m68k_read8_misc: + bic r2, r0, #0x00ff + bic r2, r2, #0xbf00 + cmp r2, #0xa00000 @ Z80 RAM? + beq z80Read8 +@ ldreq r2, =z80Read8 +@ bxeq r2 + stmfd sp!,{r0,lr} + bic r0, r0, #1 + mov r1, #8 + bl OtherRead16 @ non-MCD version should be ok too + ldmfd sp!,{r1,lr} + tst r1, #1 + moveq r0, r0, lsr #8 + bx lr + + +m_m68k_read8_vdp: + tst r0, #0x70000 + tsteq r0, #0x000e0 + bxne lr @ invalid read + stmfd sp!,{r0,lr} + bic r0, r0, #1 + bl PicoVideoRead @ TODO: implement it in asm + ldmfd sp!,{r1,lr} + tst r1, #1 + moveq r0, r0, lsr #8 + bx lr + + +m_m68k_read8_ram: + ldr r1, =Pico + bic r0, r0, #0xff0000 + eor r0, r0, #1 + ldrb r0, [r1, r0] + bx lr + + +@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + + +m_m68k_read16_bios: + ldr r1, =(Pico+0x22200) + bic r0, r0, #0xfe0000 + ldr r1, [r1] + bic r0, r0, #1 + ldrh r0, [r1, r0] + bx lr + + +m_m68k_read16_prgbank: + ldr r1, =(Pico+0x22200) + bic r0, r0, #1 + ldr r1, [r1] + mov r2, #0x110000 + orr r3, r2, #0x002200 + ldr r3, [r1, r3] + ldr r2, [r1, r2] + tst r3, #0x00020000 @ have bus? + moveq r0, #0 + bxeq lr + and r2, r2, #0xc0000000 @ r3 & 0xC0 + add r1, r1, r2, lsr #12 + ldrh r0, [r1, r0] + bx lr + + +m_m68k_read16_wordram0_2M: @ 0x200000 - 0x21ffff +m_m68k_read16_wordram1_2M: @ 0x220000 - 0x23ffff + ldr r1, =(Pico+0x22200) + sub r0, r0, #0x160000 @ map to our offset, which is 0x0a0000 + ldr r1, [r1] + bic r0, r0, #1 + ldrh r0, [r1, r0] + bx lr + + +m_m68k_read16_wordram0_1M_b0: @ 0x200000 - 0x21ffff + ldr r1, =(Pico+0x22200) + sub r0, r0, #0x140000 @ map to our offset, which is 0x0c0000 + ldr r1, [r1] + bic r0, r0, #1 + ldrh r0, [r1, r0] + bx lr + + +m_m68k_read16_wordram0_1M_b1: @ 0x200000 - 0x21ffff + ldr r1, =(Pico+0x22200) + sub r0, r0, #0x120000 @ map to our offset, which is 0x0e0000 + ldr r1, [r1] + bic r0, r0, #1 + ldrh r0, [r1, r0] + bx lr + + +m_m68k_read16_wordram1_1M_b0: @ 0x220000 - 0x23ffff, cell arranged + @ Warning: read32 relies on NOT using r3 and r12 here + cell_map + ldr r1, =(Pico+0x22200) + add r0, r0, #0x0c0000 + ldr r1, [r1] + bic r0, r0, #1 + ldrh r0, [r1, r0] + bx lr + + +m_m68k_read16_wordram1_1M_b1: @ 0x220000 - 0x23ffff, cell arranged + cell_map + ldr r1, =(Pico+0x22200) + add r0, r0, #0x0e0000 + ldr r1, [r1] + bic r0, r0, #1 + ldrh r0, [r1, r0] + bx lr + + +m_m68k_read16_system_io: + bic r1, r0, #0xfe0000 + bic r1, r1, #0x3f + cmp r1, #0x012000 + bne m_m68k_read16_misc + +m_m68k_read16_m68k_regs: + ldr r1, =(Pico+0x22200) + and r0, r0, #0x3e + ldr r1, [r1] @ Pico.mcd (used everywhere) + cmp r0, #0x0e + ldrlt pc, [pc, r0, lsl #1] + b m_m68k_read16_hi + .long m_m68k_read16_r00 + .long m_m68k_read16_r02 + .long m_m68k_read16_r04 + .long m_m68k_read16_r06 + .long m_m68k_read16_r08 + .long m_read_null @ reserved + .long m_m68k_read16_r0c +m_m68k_read16_r00: + add r1, r1, #0x110000 + ldr r0, [r1, #30] + add r1, r1, #0x002200 + ldrb r1, [r1, #2] @ Pico_mcd->m.busreq + and r0, r0, #0x04000000 @ we need irq2 mask state + orr r0, r1, r0, lsr #11 + bx lr +m_m68k_read16_r02: + add r1, r1, #0x110000 + ldrb r0, [r1, #2] + ldrb r1, [r1, #3] + and r1, r1, #0xc7 + orr r0, r1, r0, lsl #8 + bx lr +m_m68k_read16_r04: + add r1, r1, #0x110000 + ldrb r0, [r1, #4] + mov r0, r0, lsl #8 + bx lr +m_m68k_read16_r06: + ldrh r0, [r1, #0x72] @ IRQ vector + bx lr +m_m68k_read16_r08: + mov r0, #0 + b Read_CDC_Host +m_m68k_read16_r0c: + add r1, r1, #0x110000 + add r1, r1, #0x002200 + ldr r0, [r1, #0x14] + mov r0, r0, lsr #16 + bx lr +m_m68k_read16_hi: + cmp r0, #0x30 + addlt r1, r1, #0x110000 + ldrlth r1, [r1, r0] + movge r0, #0 + bxge lr + mov r0, r1, lsr #8 + and r1, r1, #0xff + orr r0, r0, r1, lsl #8 + bx lr + + +m_m68k_read16_misc: + bic r0, r0, #1 + mov r1, #16 + b OtherRead16 + + +m_m68k_read16_vdp: + tst r0, #0x70000 + tsteq r0, #0x000e0 + bxne lr @ invalid read + bic r0, r0, #1 + b PicoVideoRead + + +m_m68k_read16_ram: + ldr r1, =Pico + bic r0, r0, #0xff0000 + bic r0, r0, #1 + ldrh r0, [r1, r0] + bx lr + + +@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + + +m_m68k_read32_bios: + ldr r1, =(Pico+0x22200) + bic r0, r0, #0xfe0000 + ldr r1, [r1] + bic r0, r0, #1 + m_read32_gen + bx lr + + +m_m68k_read32_prgbank: + ldr r1, =(Pico+0x22200) + bic r0, r0, #1 + ldr r1, [r1] + mov r2, #0x110000 + orr r3, r2, #0x002200 + ldr r3, [r1, r3] + ldr r2, [r1, r2] + tst r3, #0x00020000 @ have bus? + moveq r0, #0 + bxeq lr + and r2, r2, #0xc0000000 @ r3 & 0xC0 + add r1, r1, r2, lsr #12 + m_read32_gen + bx lr + + +m_m68k_read32_wordram0_2M: @ 0x200000 - 0x21ffff +m_m68k_read32_wordram1_2M: @ 0x220000 - 0x23ffff + ldr r1, =(Pico+0x22200) + sub r0, r0, #0x160000 @ map to our offset, which is 0x0a0000 + ldr r1, [r1] + bic r0, r0, #1 + m_read32_gen + bx lr + + +m_m68k_read32_wordram0_1M_b0: @ 0x200000 - 0x21ffff + ldr r1, =(Pico+0x22200) + sub r0, r0, #0x140000 @ map to our offset, which is 0x0c0000 + ldr r1, [r1] + bic r0, r0, #1 + m_read32_gen + bx lr + + +m_m68k_read32_wordram0_1M_b1: @ 0x200000 - 0x21ffff + ldr r1, =(Pico+0x22200) + sub r0, r0, #0x120000 @ map to our offset, which is 0x0e0000 + ldr r1, [r1] + bic r0, r0, #1 + m_read32_gen + bx lr + + +m_m68k_read32_wordram1_1M_b0: @ 0x220000 - 0x23ffff, cell arranged + tst r0, #2 + bne m_m68k_read32_wordram1_1M_b0_unal + cell_map + ldr r1, =(Pico+0x22200) + add r0, r0, #0x0c0000 + ldr r1, [r1] + bic r0, r0, #1 + m_read32_gen + bx lr +m_m68k_read32_wordram1_1M_b0_unal: + @ hopefully this doesn't happen too often + mov r12,lr + mov r3, r0 + bl m_m68k_read16_wordram1_1M_b0 @ must not trash r12 and r3 + add r1, r3, #2 + mov r3, r0 + mov r0, r1 + bl m_m68k_read16_wordram1_1M_b0 + orr r0, r0, r3, lsl #16 + bx r12 + + +m_m68k_read32_wordram1_1M_b1: @ 0x220000 - 0x23ffff, cell arranged + tst r0, #2 + bne m_m68k_read32_wordram1_1M_b1_unal + cell_map + ldr r1, =(Pico+0x22200) + add r0, r0, #0x0e0000 + ldr r1, [r1] + bic r0, r0, #1 + m_read32_gen + bx lr +m_m68k_read32_wordram1_1M_b1_unal: + mov r12,lr + mov r3, r0 + bl m_m68k_read16_wordram1_1M_b1 @ must not trash r12 and r3 + add r1, r3, #2 + mov r3, r0 + mov r0, r1 + bl m_m68k_read16_wordram1_1M_b1 + orr r0, r0, r3, lsl #16 + bx r12 + + +@ it is not very practical to use long access on hw registers, so I assume it is not used too much. +m_m68k_read32_system_io: + bic r1, r0, #0xfe0000 + bic r1, r1, #0x3f + cmp r1, #0x012000 + bne m_m68k_read32_misc + and r1, r0, #0x3e + cmp r1, #0x0e + blt m_m68k_read32_misc + cmp r1, #0x30 + movge r0, #0 + bxge lr + @ I have seen the range 0x0e-0x2f accessed quite frequently with long i/o, so here is some code for that + ldr r0, =(Pico+0x22200) + mov r2, #0xff + ldr r0, [r0] + orr r2, r2, r2, lsl #16 + add r0, r0, #0x110000 + m_read32_gen + and r1, r2, r0 @ data is big-endian read as little, have to byteswap + and r0, r2, r0, lsr #8 + orr r0, r0, r1, lsl #8 + bx lr + +m_m68k_read32_misc: + add r1, r0, #2 + stmfd sp!,{r1,lr} + bl m_m68k_read16_system_io + swp r0, r0, [sp] + bl m_m68k_read16_system_io + ldmfd sp!,{r1,lr} + orr r0, r0, r1, lsl #16 + bx lr + + +m_m68k_read32_vdp: + tst r0, #0x70000 + tsteq r0, #0x000e0 + bxne lr @ invalid read + bic r0, r0, #1 + add r1, r0, #2 + stmfd sp!,{r1,lr} + bl PicoVideoRead + swp r0, r0, [sp] + bl PicoVideoRead + ldmfd sp!,{r1,lr} + orr r0, r0, r1, lsl #16 + bx lr + + +m_m68k_read32_ram: + ldr r1, =Pico + bic r0, r0, #0xff0000 + bic r0, r0, #1 + m_read32_gen + bx lr + +.pool + +@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + + +m_write_null: +m_m68k_write8_bios: + bx lr + + +m_m68k_write8_prgbank: + ldr r2, =(Pico+0x22200) + eor r0, r0, #1 + ldr r2, [r2] + mov r12,#0x110000 + orr r3, r12, #0x002200 + ldr r3, [r2, r3] + ldr r12,[r2, r12] + tst r3, #0x00020000 @ have bus? + bxeq lr + and r12,r12,#0xc0000000 @ r3 & 0xC0 + add r2, r2, r12, lsr #12 + strb r1, [r2, r0] + bx lr + + +m_m68k_write8_wordram0_2M: @ 0x200000 - 0x21ffff +m_m68k_write8_wordram1_2M: @ 0x220000 - 0x23ffff + ldr r2, =(Pico+0x22200) + sub r0, r0, #0x160000 @ map to our offset, which is 0x0a0000 + ldr r2, [r2] + eor r0, r0, #1 + strb r1, [r2, r0] + bx lr + + +m_m68k_write8_wordram0_1M_b0: @ 0x200000 - 0x21ffff + ldr r2, =(Pico+0x22200) + sub r0, r0, #0x140000 @ map to our offset, which is 0x0c0000 + ldr r2, [r2] + eor r0, r0, #1 + strb r1, [r2, r0] + bx lr + + +m_m68k_write8_wordram0_1M_b1: @ 0x200000 - 0x21ffff + ldr r2, =(Pico+0x22200) + sub r0, r0, #0x120000 @ map to our offset, which is 0x0e0000 + ldr r2, [r2] + eor r0, r0, #1 + strb r1, [r2, r0] + bx lr + + +m_m68k_write8_wordram1_1M_b0: @ 0x220000 - 0x23ffff, cell arranged + mov r3, r1 + cell_map + ldr r2, =(Pico+0x22200) + add r0, r0, #0x0c0000 + ldr r2, [r2] + eor r0, r0, #1 + strb r3, [r2, r0] + bx lr + + +m_m68k_write8_wordram1_1M_b1: @ 0x220000 - 0x23ffff, cell arranged + mov r3, r1 + cell_map + ldr r2, =(Pico+0x22200) + add r0, r0, #0x0e0000 + ldr r2, [r2] + eor r0, r0, #1 + strb r3, [r2, r0] + bx lr + + +m_m68k_write8_system_io: + bic r2, r0, #0xfe0000 + bic r2, r2, #0x3f + cmp r2, #0x012000 + beq m68k_reg_write8 + mov r2, #8 + b OtherWrite8 + + +m_m68k_write8_vdp: + tst r0, #0x70000 + tsteq r0, #0x000e0 + bxne lr @ invalid + and r1, r1, #0xff + orr r1, r1, r1, lsl #8 @ byte access gets mirrored + b PicoVideoWrite + + +m_m68k_write8_ram: + ldr r2, =Pico + bic r0, r0, #0xff0000 + eor r0, r0, #1 + strb r1, [r2, r0] + bx lr + + +@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + + +m_m68k_write16_bios: + bx lr + + +m_m68k_write16_prgbank: + ldr r2, =(Pico+0x22200) + bic r0, r0, #1 + ldr r2, [r2] + mov r12,#0x110000 + orr r3, r12, #0x002200 + ldr r3, [r2, r3] + ldr r12,[r2, r12] + tst r3, #0x00020000 @ have bus? + bxeq lr + and r12,r12,#0xc0000000 @ r3 & 0xC0 + add r2, r2, r12, lsr #12 + strh r1, [r2, r0] + bx lr + + +m_m68k_write16_wordram0_2M: @ 0x200000 - 0x21ffff +m_m68k_write16_wordram1_2M: @ 0x220000 - 0x23ffff + ldr r2, =(Pico+0x22200) + sub r0, r0, #0x160000 @ map to our offset, which is 0x0a0000 + ldr r2, [r2] + bic r0, r0, #1 + strh r1, [r2, r0] + bx lr + + +m_m68k_write16_wordram0_1M_b0: @ 0x200000 - 0x21ffff + ldr r2, =(Pico+0x22200) + sub r0, r0, #0x140000 @ map to our offset, which is 0x0c0000 + ldr r2, [r2] + bic r0, r0, #1 + strh r1, [r2, r0] + bx lr + + +m_m68k_write16_wordram0_1M_b1: @ 0x200000 - 0x21ffff + ldr r2, =(Pico+0x22200) + sub r0, r0, #0x120000 @ map to our offset, which is 0x0e0000 + ldr r2, [r2] + bic r0, r0, #1 + strh r1, [r2, r0] + bx lr + + +m_m68k_write16_wordram1_1M_b0: @ 0x220000 - 0x23ffff, cell arranged + @ Warning: write32 relies on NOT using r12 and and keeping data in r3 + mov r3, r1 + cell_map + ldr r1, =(Pico+0x22200) + add r0, r0, #0x0c0000 + ldr r1, [r1] + bic r0, r0, #1 + strh r3, [r1, r0] + bx lr + + +m_m68k_write16_wordram1_1M_b1: @ 0x220000 - 0x23ffff, cell arranged + mov r3, r1 + cell_map + ldr r1, =(Pico+0x22200) + add r0, r0, #0x0e0000 + ldr r1, [r1] + bic r0, r0, #1 + strh r3, [r1, r0] + bx lr + + +m_m68k_write16_system_io: + bic r0, r0, #1 + bic r2, r0, #0xfe0000 + bic r2, r2, #0x3f + cmp r2, #0x012000 + bne OtherWrite16 + +m_m68k_write16_m68k_regs: + and r3, r1, #0xff + add r2, r0, #1 + stmfd sp!,{r2,r3,lr} + mov r1, r1, lsr #8 + bl m68k_reg_write8 + ldmfd sp!,{r0,r1,lr} + b m68k_reg_write8 + + +m_m68k_write16_vdp: + tst r0, #0x70000 + tsteq r0, #0x000e0 + bxne lr @ invalid + bic r0, r0, #1 + b PicoVideoWrite + + +m_m68k_write16_ram: + ldr r2, =Pico + bic r0, r0, #0xff0000 + bic r0, r0, #1 + strh r1, [r2, r0] + bx lr + + +@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + + +m_m68k_write32_bios: + bx lr + + +m_m68k_write32_prgbank: + ldr r2, =(Pico+0x22200) + bic r0, r0, #1 + ldr r2, [r2] + mov r12,#0x110000 + orr r3, r12, #0x002200 + ldr r3, [r2, r3] + ldr r12,[r2, r12] + tst r3, #0x00020000 @ have bus? + bxeq lr + and r12,r12,#0xc0000000 @ r3 & 0xC0 + add r2, r2, r12, lsr #12 + m_write32_gen + bx lr + + +m_m68k_write32_wordram0_2M: @ 0x200000 - 0x21ffff +m_m68k_write32_wordram1_2M: @ 0x220000 - 0x23ffff + ldr r2, =(Pico+0x22200) + sub r0, r0, #0x160000 @ map to our offset, which is 0x0a0000 + ldr r2, [r2] + bic r0, r0, #1 + m_write32_gen + bx lr + + +m_m68k_write32_wordram0_1M_b0: @ 0x200000 - 0x21ffff + ldr r2, =(Pico+0x22200) + sub r0, r0, #0x140000 @ map to our offset, which is 0x0c0000 + ldr r2, [r2] + bic r0, r0, #1 + m_write32_gen + bx lr + + +m_m68k_write32_wordram0_1M_b1: @ 0x200000 - 0x21ffff + ldr r2, =(Pico+0x22200) + sub r0, r0, #0x120000 @ map to our offset, which is 0x0e0000 + ldr r2, [r2] + bic r0, r0, #1 + m_write32_gen + bx lr + + +m_m68k_write32_wordram1_1M_b0: @ 0x220000 - 0x23ffff, cell arranged + tst r0, #2 + bne m_m68k_write32_wordram1_1M_b0_unal + mov r3, r1 + cell_map + ldr r2, =(Pico+0x22200) + add r0, r0, #0x0c0000 + ldr r2, [r2] + bic r0, r0, #1 + mov r1, r3 + m_write32_gen + bx lr +m_m68k_write32_wordram1_1M_b0_unal: + @ hopefully this doesn't happen too often + add r12,r0, #2 + mov r1, r1, ror #16 + stmfd sp!,{lr} + bl m_m68k_write16_wordram1_1M_b0 @ must not trash r12 and keep data in r3 + ldmfd sp!,{lr} + mov r0, r12 + mov r1, r3, lsr #16 + b m_m68k_write16_wordram1_1M_b0 + + +m_m68k_write32_wordram1_1M_b1: @ 0x220000 - 0x23ffff, cell arranged + tst r0, #2 + bne m_m68k_write32_wordram1_1M_b1_unal + mov r3, r1 + cell_map + ldr r2, =(Pico+0x22200) + add r0, r0, #0x0e0000 + ldr r2, [r2] + bic r0, r0, #1 + mov r1, r3 + m_write32_gen + bx lr +m_m68k_write32_wordram1_1M_b1_unal: + add r12,r0, #2 + mov r1, r1, ror #16 + stmfd sp!,{lr} + bl m_m68k_write16_wordram1_1M_b1 @ same as above + ldmfd sp!,{lr} + mov r0, r12 + mov r1, r3, lsr #16 + b m_m68k_write16_wordram1_1M_b1 + + +@ it is not very practical to use long access on hw registers, so I assume it is not used too much. +m_m68k_write32_system_io: + bic r2, r0, #0xfe0000 + bic r2, r2, #0x3f + cmp r2, #0x012000 + bne m_m68k_write32_misc + and r2, r0, #0x3e + cmp r2, #0x10 + blt m_m68k_write32_regs + cmp r2, #0x20 + bxge lr + @ Handle the 0x10-0x1f range + ldr r0, =(Pico+0x22200) + mov r3, #0xff + ldr r0, [r0] + orr r3, r3, r3, lsl #16 + add r0, r0, #0x110000 + and r12,r3, r1, ror #16 @ data is big-endian to be written as little, have to byteswap + and r1, r3, r1, ror #24 + orr r1, r1, r12,lsl #8 @ end of byteswap + strh r1, [r2, r0]! + cmp r2, #0x1e + movne r1, r1, lsr #16 + strneh r1, [r2, #2] + bx lr + +m_m68k_write32_regs: + stmfd sp!,{r0,r1,lr} + mov r1, r1, lsr #24 + bl m68k_reg_write8 + ldr r0, [sp] + ldr r1, [sp, #4] + add r0, r0, #1 + mov r1, r1, lsr #16 + bl m68k_reg_write8 + ldr r0, [sp] + ldr r1, [sp, #4] + add r0, r0, #2 + mov r1, r1, lsr #8 + bl m68k_reg_write8 + ldmfd sp!,{r0,r1,lr} + add r0, r0, #3 + b m68k_reg_write8 + +m_m68k_write32_misc: + stmfd sp!,{r0,r1,lr} + mov r1, r1, lsr #16 + bl OtherWrite16 + ldmfd sp!,{r0,r1,lr} + add r0, r0, #2 + b OtherWrite16 + + +m_m68k_write32_vdp: + tst r0, #0x70000 + tsteq r0, #0x000e0 + bxne lr @ invalid + stmfd sp!,{r0,r1,lr} + mov r1, r1, lsr #16 + bl PicoVideoWrite + ldmfd sp!,{r0,r1,lr} + add r0, r0, #2 + b PicoVideoWrite + + +m_m68k_write32_ram: + ldr r2, =Pico + bic r0, r0, #0xff0000 + bic r0, r0, #1 + m_write32_gen + bx lr + +.pool + + +@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + + +m_s68k_read8_prg: @ 0x000000 - 0x07ffff + ldr r1, =(Pico+0x22200) + eor r0, r0, #1 + ldr r1, [r1] + add r0, r0, #0x020000 @ map to our address + ldrb r0, [r1, r0] + bx lr + + +m_s68k_read8_wordram_2M: @ 0x080000 - 0x0bffff + ldr r1, =(Pico+0x22200) + eor r0, r0, #1 + ldr r1, [r1] + add r0, r0, #0x020000 @ map to our address (0x0a0000) + ldrb r0, [r1, r0] + bx lr + + +m_s68k_read8_wordram_2M_decode_b0: @ 0x080000 - 0x0bffff +m_s68k_read8_wordram_2M_decode_b1: @ 0x080000 - 0x0bffff + mov r0, #0 + bx lr @ TODO + + +m_s68k_read8_wordram_1M_b0: @ 0x0c0000 - 0x0dffff (same as our offset :) + ldr r1, =(Pico+0x22200) + ldr r1, [r1] + eor r0, r0, #1 + ldrb r0, [r1, r0] + bx lr + + +m_s68k_read8_wordram_1M_b1: @ 0x0c0000 - 0x0dffff + ldr r1, =(Pico+0x22200) + add r0, r0, #0x020000 @ map to our offset, which is 0x0e0000 + ldr r1, [r1] + eor r0, r0, #1 + ldrb r0, [r1, r0] + bx lr + + +m_s68k_read8_backup: @ 0xfe0000 - 0xfe3fff (repeated?) + @ must not trash r3 and r12 + ldr r1, =(Pico+0x22200) + mov r0, r0, lsr #1 + ldr r1, [r1] + bic r0, r0, #0xff0000 + bic r0, r0, #0x00fe00 + add r1, r1, #0x110000 + add r1, r1, #0x000200 + ldrb r0, [r1, r0] + bx lr + + +m_s68k_read8_pcm: + @ must not trash r3 and r12 + ldr r1, =(Pico+0x22200) + bic r0, r0, #0xff0000 +@ bic r0, r0, #0x008000 + ldr r1, [r1] + mov r2, #0x110000 + orr r2, r2, #0x002200 + cmp r0, #0x2000 + bge m_s68k_read8_pcm_ram + cmp r0, #0x20 + movlt r0, #0 + bxlt lr + orr r2, r2, #(0x48+8) @ pcm.ch + addr_offset + add r1, r1, r2 + and r2, r0, #0x1c + ldr r1, [r1, r2, lsl #2] + tst r0, #2 + moveq r0, r1, lsr #PCM_STEP_SHIFT + movne r0, r1, lsr #(PCM_STEP_SHIFT+8) + and r0, r0, #0xff + bx lr + +m_s68k_read8_pcm_ram: + orr r2, r2, #0x40 + ldr r2, [r1, r2] + add r1, r1, #0x100000 @ pcm_ram + and r2, r2, #0x0f000000 @ bank + add r1, r1, r2, lsr #12 + bic r0, r0, #0x00e000 + mov r0, r0, lsr #1 + ldrb r0, [r1, r0] + bx lr + + +m_s68k_read8_regs: + bic r0, r0, #0xff0000 + bic r0, r0, #0x008000 + tst r0, #0x7e00 + movne r0, #0 + bxne lr + sub r2, r0, #0x58 + cmp r2, #0x10 + ldrlo r2, =gfx_cd_read + ldrhs r2, =s68k_reg_read16 + stmfd sp!,{r0,lr} + bic r0, r0, #1 + mov lr, pc + bx r2 + ldmfd sp!,{r1,lr} + tst r1, #1 + moveq r0, r0, lsr #8 + and r0, r0, #0xff + bx lr + + +@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + + +m_s68k_read16_prg: @ 0x000000 - 0x07ffff + ldr r1, =(Pico+0x22200) + bic r0, r0, #1 + ldr r1, [r1] + add r0, r0, #0x020000 @ map to our address + ldrh r0, [r1, r0] + bx lr + + +m_s68k_read16_wordram_2M: @ 0x080000 - 0x0bffff + ldr r1, =(Pico+0x22200) + bic r0, r0, #1 + ldr r1, [r1] + add r0, r0, #0x020000 @ map to our address (0x0a0000) + ldrh r0, [r1, r0] + bx lr + + +m_s68k_read16_wordram_2M_decode_b0: @ 0x080000 - 0x0bffff +m_s68k_read16_wordram_2M_decode_b1: @ 0x080000 - 0x0bffff + mov r0, #0 + bx lr @ TODO + + +m_s68k_read16_wordram_1M_b0: @ 0x0c0000 - 0x0dffff (same as our offset :) + ldr r1, =(Pico+0x22200) + ldr r1, [r1] + bic r0, r0, #1 + ldrh r0, [r1, r0] + bx lr + + +m_s68k_read16_wordram_1M_b1: @ 0x0c0000 - 0x0dffff + ldr r1, =(Pico+0x22200) + add r0, r0, #0x020000 @ map to our offset, which is 0x0e0000 + ldr r1, [r1] + bic r0, r0, #1 + ldrh r0, [r1, r0] + bx lr + + +@ m_s68k_read16_backup: @ 0xfe0000 - 0xfe3fff (repeated?) +@ bram is not meant to be accessed by words, does any game do this? +.equiv m_s68k_read16_backup, m_s68k_read8_backup + + +@ m_s68k_read16_pcm: +@ pcm is on 8-bit bus, would this be same as byte access? +.equiv m_s68k_read16_pcm, m_s68k_read8_pcm + + +m_s68k_read16_regs: + bic r0, r0, #0xff0000 + bic r0, r0, #0x008000 + bic r0, r0, #0x000001 + tst r0, #0x7e00 + movne r0, #0 + bxne lr + sub r2, r0, #0x58 + cmp r2, #0x10 + blo gfx_cd_read + b s68k_reg_read16 + + +@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + + +m_s68k_read32_prg: @ 0x000000 - 0x07ffff + ldr r1, =(Pico+0x22200) + bic r0, r0, #1 + ldr r1, [r1] + add r0, r0, #0x020000 @ map to our address + m_read32_gen + bx lr + + +m_s68k_read32_wordram_2M: @ 0x080000 - 0x0bffff + ldr r1, =(Pico+0x22200) + bic r0, r0, #1 + ldr r1, [r1] + add r0, r0, #0x020000 @ map to our address (0x0a0000) + m_read32_gen + bx lr + + +m_s68k_read32_wordram_2M_decode_b0: @ 0x080000 - 0x0bffff +m_s68k_read32_wordram_2M_decode_b1: @ 0x080000 - 0x0bffff + mov r0, #0 + bx lr @ TODO + + +m_s68k_read32_wordram_1M_b0: @ 0x0c0000 - 0x0dffff (same as our offset :) + ldr r1, =(Pico+0x22200) + ldr r1, [r1] + bic r0, r0, #1 + m_read32_gen + bx lr + + +m_s68k_read32_wordram_1M_b1: @ 0x0c0000 - 0x0dffff + ldr r1, =(Pico+0x22200) + add r0, r0, #0x020000 @ map to our offset, which is 0x0e0000 + ldr r1, [r1] + bic r0, r0, #1 + m_read32_gen + bx lr + + +m_s68k_read32_backup: @ 0xfe0000 - 0xfe3fff (repeated?) + @ bram is not meant to be accessed by words, does any game do this? + mov r12,lr + mov r3, r0 + bl m_s68k_read8_backup @ must preserve r3 and r12 + mov r1, r0 + add r0, r3, #2 + mov r3, r1 + bl m_s68k_read8_backup + orr r0, r0, r3, lsl #16 + bx r12 + + +m_s68k_read32_pcm: + mov r12,lr + mov r3, r0 + bl m_s68k_read8_pcm @ must preserve r3 and r12 + mov r1, r0 + add r0, r3, #2 + mov r3, r1 + bl m_s68k_read8_pcm + orr r0, r0, r3, lsl #16 + bx r12 + + +m_s68k_read32_regs: + bic r0, r0, #0xff0000 + bic r0, r0, #0x008000 + bic r0, r0, #0x000001 + tst r0, #0x7e00 + movne r0, #0 + bxne lr + sub r2, r0, #0x58 + cmp r2, #0x10 + add r1, r0, #2 + blo m_s68k_read32_regs_gfx + stmfd sp!,{r1,lr} + bl s68k_reg_read16 + swp r0, r0, [sp] + bl s68k_reg_read16 + ldmfd sp!,{r1,lr} + orr r0, r0, r1, lsl #16 + bx lr + + +m_s68k_read32_regs_gfx: + stmfd sp!,{r1,lr} + bl gfx_cd_read + swp r0, r0, [sp] + bl gfx_cd_read + ldmfd sp!,{r1,lr} + orr r0, r0, r1, lsl #16 + bx lr + +.pool + +@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + + +m_s68k_write8_prg: @ 0x000000 - 0x07ffff + ldr r2, =(Pico+0x22200) + eor r0, r0, #1 + ldr r2, [r2] + add r0, r0, #0x020000 @ map to our address + strb r1, [r2, r0] + bx lr + + +m_s68k_write8_wordram_2M: @ 0x080000 - 0x0bffff + ldr r2, =(Pico+0x22200) + eor r0, r0, #1 + ldr r2, [r2] + add r0, r0, #0x020000 @ map to our address (0x0a0000) + strb r1, [r2, r0] + bx lr + + +m_s68k_write8_wordram_2M_decode_b0: @ 0x080000 - 0x0bffff +m_s68k_write8_wordram_2M_decode_b1: @ 0x080000 - 0x0bffff + bx lr @ TODO + + +m_s68k_write8_wordram_1M_b0: @ 0x0c0000 - 0x0dffff (same as our offset :) + ldr r2, =(Pico+0x22200) + ldr r2, [r2] + eor r0, r0, #1 + strb r1, [r2, r0] + bx lr + + +m_s68k_write8_wordram_1M_b1: @ 0x0c0000 - 0x0dffff + ldr r2, =(Pico+0x22200) + add r0, r0, #0x020000 @ map to our offset, which is 0x0e0000 + ldr r2, [r2] + eor r0, r0, #1 + strb r1, [r2, r0] + bx lr + + +m_s68k_write8_backup: @ 0xfe0000 - 0xfe3fff (repeated?) + @ must not trash r3 and r12 + ldr r2, =(Pico+0x22200) + mov r0, r0, lsr #1 + ldr r2, [r2] + bic r0, r0, #0xff0000 + bic r0, r0, #0x00fe00 + add r2, r2, #0x110000 + add r2, r2, #0x000200 + strb r1, [r2, r0] + ldr r1, =SRam + mov r0, #1 + str r0, [r1, #0x0e] @ SRam.changed = 1 + bx lr + + +m_s68k_write8_pcm: + bic r0, r0, #0xff0000 + cmp r0, #0x12 + movlt r0, r0, lsr #1 + blt pcm_write + + cmp r0, #0x2000 + bxlt lr + +m_s68k_write8_pcm_ram: + ldr r3, =(Pico+0x22200) + bic r0, r0, #0x00e000 + ldr r3, [r3] + mov r0, r0, lsr #1 + add r2, r3, #0x110000 + add r2, r2, #0x002200 + add r2, r2, #0x000040 + ldr r2, [r2] + add r3, r3, #0x100000 @ pcm_ram + and r2, r2, #0x0f000000 @ bank + add r3, r3, r2, lsr #12 + strb r1, [r3, r0] + bx lr + + +m_s68k_write8_regs: + bic r0, r0, #0xff0000 + bic r0, r0, #0x008000 + tst r0, #0x7e00 + movne r0, #0 + bxne lr + sub r2, r0, #0x58 + cmp r2, #0x10 + blo gfx_cd_write + b s68k_reg_write8 + + +@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + + +m_s68k_write16_prg: @ 0x000000 - 0x07ffff + ldr r2, =(Pico+0x22200) + bic r0, r0, #1 + ldr r2, [r2] + add r0, r0, #0x020000 @ map to our address + strh r1, [r2, r0] + bx lr + + +m_s68k_write16_wordram_2M: @ 0x080000 - 0x0bffff + ldr r2, =(Pico+0x22200) + bic r0, r0, #1 + ldr r2, [r2] + add r0, r0, #0x020000 @ map to our address (0x0a0000) + strh r1, [r2, r0] + bx lr + + +m_s68k_write16_wordram_2M_decode_b0: @ 0x080000 - 0x0bffff +m_s68k_write16_wordram_2M_decode_b1: @ 0x080000 - 0x0bffff + bx lr @ TODO + + +m_s68k_write16_wordram_1M_b0: @ 0x0c0000 - 0x0dffff (same as our offset :) + ldr r2, =(Pico+0x22200) + ldr r2, [r2] + bic r0, r0, #1 + strh r1, [r2, r0] + bx lr + + +m_s68k_write16_wordram_1M_b1: @ 0x0c0000 - 0x0dffff + ldr r2, =(Pico+0x22200) + add r0, r0, #0x020000 @ map to our offset, which is 0x0e0000 + ldr r2, [r2] + bic r0, r0, #1 + strh r1, [r2, r0] + bx lr + + +@ m_s68k_write16_backup: +.equiv m_s68k_write16_backup, m_s68k_write8_backup + + +@ m_s68k_write16_pcm: +.equiv m_s68k_write16_pcm, m_s68k_write8_pcm + + +m_s68k_write16_regs: + bic r0, r0, #0xff0000 + bic r0, r0, #0x008000 + tst r0, #0x7e00 + movne r0, #0 + bxne lr + sub r2, r0, #0x58 + cmp r2, #0x10 + and r3, r1, #0xff + add r2, r0, #1 + blo m_s68k_write16_regs_gfx + stmfd sp!,{r2,r3,lr} + mov r1, r1, lsr #8 + bl s68k_reg_write8 + ldmfd sp!,{r0,r1,lr} + b s68k_reg_write8 + +m_s68k_write16_regs_gfx: + stmfd sp!,{r2,r3,lr} + mov r1, r1, lsr #8 + bl gfx_cd_write + ldmfd sp!,{r0,r1,lr} + b gfx_cd_write + + +@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + + +m_s68k_write32_prg: @ 0x000000 - 0x07ffff + ldr r2, =(Pico+0x22200) + bic r0, r0, #1 + ldr r2, [r2] + add r0, r0, #0x020000 @ map to our address + m_write32_gen + bx lr + + +m_s68k_write32_wordram_2M: @ 0x080000 - 0x0bffff + ldr r2, =(Pico+0x22200) + bic r0, r0, #1 + ldr r2, [r2] + add r0, r0, #0x020000 @ map to our address (0x0a0000) + m_write32_gen + bx lr + + +m_s68k_write32_wordram_2M_decode_b0: @ 0x080000 - 0x0bffff +m_s68k_write32_wordram_2M_decode_b1: @ 0x080000 - 0x0bffff + bx lr @ TODO + + +m_s68k_write32_wordram_1M_b0: @ 0x0c0000 - 0x0dffff (same as our offset :) + ldr r2, =(Pico+0x22200) + ldr r2, [r2] + bic r0, r0, #1 + m_write32_gen + bx lr + + +m_s68k_write32_wordram_1M_b1: @ 0x0c0000 - 0x0dffff + ldr r2, =(Pico+0x22200) + add r0, r0, #0x020000 @ map to our offset, which is 0x0e0000 + ldr r2, [r2] + bic r0, r0, #1 + m_write32_gen + bx lr + + +m_s68k_write32_backup: + add r12,r0, #2 + mov r3, r1 + mov r1, r1, lsr #16 + stmfd sp!,{lr} + bl m_s68k_write8_backup @ must preserve r3 and r12 + ldmfd sp!,{lr} + mov r0, r12 + mov r1, r3 + b m_s68k_write8_backup + + +m_s68k_write32_pcm: + bic r0, r0, #0xff0000 + cmp r0, #0x12 + blt m_s68k_write32_pcm_reg + + cmp r0, #0x2000 + bxlt lr + +m_s68k_write32_pcm_ram: + ldr r3, =(Pico+0x22200) + bic r0, r0, #0x00e000 + ldr r3, [r3] + mov r0, r0, lsr #1 + add r2, r3, #0x110000 + add r2, r2, #0x002200 + add r2, r2, #0x000040 + ldr r2, [r2] + add r3, r3, #0x100000 @ pcm_ram + and r2, r2, #0x0f000000 @ bank + add r3, r3, r2, lsr #12 + mov r1, r1, ror #16 + strb r1, [r3, r0]! + mov r1, r1, ror #16 + strb r1, [r3] + bx lr + +m_s68k_write32_pcm_reg: + mov r0, r0, lsr #1 + add r2, r0, #1 + mov r3, r1 + stmfd sp!,{r2,r3,lr} + mov r1, r1, lsr #16 + bl pcm_write + ldmfd sp!,{r0,r1,lr} + b pcm_write + + +m_s68k_write32_regs: + bic r0, r0, #0xff0000 + bic r0, r0, #0x008000 + tst r0, #0x7e00 + movne r0, #0 + bxne lr + sub r2, r0, #0x58 + cmp r2, #0x10 + blo m_s68k_write32_regs_gfx + + stmfd sp!,{r0,r1,lr} + mov r1, r1, lsr #24 + bl s68k_reg_write8 + ldr r0, [sp] + ldr r1, [sp, #4] + add r0, r0, #1 + mov r1, r1, lsr #16 + bl s68k_reg_write8 + ldr r0, [sp] + ldr r1, [sp, #4] + add r0, r0, #2 + mov r1, r1, lsr #8 + bl s68k_reg_write8 + ldmfd sp!,{r0,r1,lr} + add r0, r0, #3 + b s68k_reg_write8 + +m_s68k_write32_regs_gfx: + stmfd sp!,{r0,r1,lr} + mov r1, r1, lsr #24 + bl gfx_cd_write + ldr r0, [sp] + ldr r1, [sp, #4] + add r0, r0, #1 + mov r1, r1, lsr #16 + bl gfx_cd_write + ldr r0, [sp] + ldr r1, [sp, #4] + add r0, r0, #2 + mov r1, r1, lsr #8 + bl gfx_cd_write + ldmfd sp!,{r0,r1,lr} + add r0, r0, #3 + b gfx_cd_write + diff --git a/Pico/cd/Pico.c b/Pico/cd/Pico.c index 4cfbbbc..cba7250 100644 --- a/Pico/cd/Pico.c +++ b/Pico/cd/Pico.c @@ -49,6 +49,9 @@ int PicoResetMCD(int hard) LC89510_Reset(); Reset_CD(); gfx_cd_reset(); +#ifdef _ASM_CD_MEMORY_C + PicoMemResetCD(1); +#endif return 0; } diff --git a/Pico/cd/cell_map.c b/Pico/cd/cell_map.c index 5358a09..4100064 100644 --- a/Pico/cd/cell_map.c +++ b/Pico/cd/cell_map.c @@ -28,7 +28,7 @@ static unsigned int cell_map(int celln) row = celln & 0x1f; row |= (celln & 0x7800) >> 6; break; - default: // just to make compiler happy + default: // never happens, only here to make compiler happy col = row = 0; break; } diff --git a/platform/gp2x/940ctl.c b/platform/gp2x/940ctl.c index 48ebfa0..b035591 100644 --- a/platform/gp2x/940ctl.c +++ b/platform/gp2x/940ctl.c @@ -99,7 +99,13 @@ int YM2612Write_940(unsigned int a, unsigned int v) switch( a ) { case 0: /* address port 0 */ + if (!addr_A1 && ST_address == v) + return 0; /* address already selected, don't send this command to 940 */ ST_address = v; + /* don't send DAC or timer related address changes to 940 */ + if (!addr_A1 && (v & 0xf0) == 0x20 && + (v == 0x24 || v == 0x25 || v == 0x26 || v == 0x2a)) + return 0; addr_A1 = 0; //ret=0; break; @@ -162,6 +168,8 @@ int YM2612Write_940(unsigned int a, unsigned int v) break; case 2: /* address port 1 */ + if (addr_A1 && ST_address == v) + return 0; ST_address = v; addr_A1 = 1; //ret=0; @@ -186,7 +194,7 @@ int YM2612Write_940(unsigned int a, unsigned int v) shared_ctl->writebuff1[writebuff_ptr++] = (a<<8)|v; } } else { - printf("warning: writebuff_ptr > 2047\n"); + printf("warning: writebuff_ptr > 2047 ([%i] %02x)\n", a, v); } } diff --git a/platform/gp2x/Makefile b/platform/gp2x/Makefile index 7818741..b045c2d 100644 --- a/platform/gp2x/Makefile +++ b/platform/gp2x/Makefile @@ -13,6 +13,7 @@ asm_render = 1 asm_ym2612 = 1 asm_misc = 1 asm_cdpico = 1 +asm_cdmemory = 1 #profile = 1 #use_musashi = 1 #up = 1 @@ -66,6 +67,10 @@ ifeq "$(asm_cdpico)" "1" DEFINC += -D_ASM_CD_PICO_C OBJS += ../../Pico/cd/pico_asm.o endif +ifeq "$(asm_cdmemory)" "1" +DEFINC += -D_ASM_CD_MEMORY_C +OBJS += ../../Pico/cd/memory_asm.o +endif # Pico - sound OBJS += ../../Pico/sound/mix_asm.o OBJS += ../../Pico/sound/sound.o ../../Pico/sound/sn76496.o ../../Pico/sound/ym2612.o @@ -147,6 +152,9 @@ testrefr.gpe : test.o gp2x.o asmutils.o ../../Pico/cd/pico_asm.o : ../../Pico/cd/Pico.s @echo $< @$(AS) $(ASOPT) $< -o $@ +../../Pico/cd/memory_asm.o : ../../Pico/cd/Memory.s + @echo $< + @$(AS) $(ASOPT) $< -o $@ # build Cyclone ../../cpu/Cyclone/proj/Cyclone.s : diff --git a/platform/gp2x/emu.c b/platform/gp2x/emu.c index 033f275..632ad18 100644 --- a/platform/gp2x/emu.c +++ b/platform/gp2x/emu.c @@ -973,21 +973,11 @@ static void updateSound(int len) } -static void SkipFrame(int do_sound) +static void SkipFrame(void) { - void *sndbuff_tmp = 0; - if (PsndOut && !do_sound) { - sndbuff_tmp = PsndOut; - PsndOut = 0; - } - PicoSkipFrame=1; PicoFrame(); PicoSkipFrame=0; - - if (sndbuff_tmp && !do_sound) { - PsndOut = sndbuff_tmp; - } } @@ -1166,7 +1156,7 @@ void emu_Loop(void) // when second changes, but we don't want buffer to starve. if(PsndOut && frames_done < target_fps && frames_done > target_fps-5) { updateKeys(); - SkipFrame(1); frames_done++; + SkipFrame(); frames_done++; } frames_done -= target_fps; if (frames_done < 0) frames_done = 0; @@ -1179,7 +1169,7 @@ void emu_Loop(void) if(currentConfig.Frameskip >= 0) { // frameskip enabled for(i = 0; i < currentConfig.Frameskip; i++) { updateKeys(); - SkipFrame(1); frames_done++; + SkipFrame(); frames_done++; if (PsndOut) { // do framelimitting if sound is enabled gettimeofday(&tval, 0); if(thissec != tval.tv_sec) tval.tv_usec+=1000000; @@ -1191,8 +1181,14 @@ void emu_Loop(void) } } else if(tval.tv_usec > lim_time) { // auto frameskip // no time left for this frame - skip + if (tval.tv_usec - lim_time >= 0x300000) { + /* something caused a slowdown for us (disk access? cache flush?) + * try to recover by resetting timing... */ + reset_timing = 1; + continue; + } updateKeys(); - SkipFrame(tval.tv_usec < lim_time+target_frametime); frames_done++; + SkipFrame(/*tval.tv_usec < lim_time+target_frametime*/); frames_done++; continue; } @@ -1259,14 +1255,14 @@ if (Pico.m.frame_count == 31563) { // check time gettimeofday(&tval, 0); - if(thissec != tval.tv_sec) tval.tv_usec+=1000000; + if (thissec != tval.tv_sec) tval.tv_usec+=1000000; - // sleep if we are still too fast - if(PsndOut != 0 || currentConfig.Frameskip < 0) + if (currentConfig.Frameskip < 0 && tval.tv_usec - lim_time >= 0x300000) // slowdown detection + reset_timing = 1; + else if (PsndOut != NULL || currentConfig.Frameskip < 0) { + // sleep if we are still too fast // usleep sleeps for ~20ms minimum, so it is not a solution here - gettimeofday(&tval, 0); - if(thissec != tval.tv_sec) tval.tv_usec+=1000000; if(tval.tv_usec < lim_time) { // we are too fast diff --git a/platform/gp2x/menu.c b/platform/gp2x/menu.c index 7050b98..5cab760 100644 --- a/platform/gp2x/menu.c +++ b/platform/gp2x/menu.c @@ -744,7 +744,7 @@ static void draw_cd_menu_options(int menu_sel, char *b_us, char *b_eu, char *b_j gp2x_text_out8(tl_x, (y+=10), "CD LEDs %s", (currentConfig.EmuOpt &0x0400)?"ON":"OFF"); // 3 gp2x_text_out8(tl_x, (y+=10), "CDDA audio (using mp3s) %s", (currentConfig.PicoOpt&0x0800)?"ON":"OFF"); // 4 gp2x_text_out8(tl_x, (y+=10), "PCM audio %s", (currentConfig.PicoOpt&0x0400)?"ON":"OFF"); // 5 - gp2x_text_out8(tl_x, (y+=10), "Better sync (slower) %s", (currentConfig.PicoOpt&0x2000)?"ON":"OFF"); // 6 + gp2x_text_out8(tl_x, (y+=10), "Better sync (slow) %s", (currentConfig.PicoOpt&0x2000)?"ON":"OFF"); // 6 gp2x_text_out8(tl_x, (y+=10), "ReadAhead buffer %s", ra_buff); // 7 gp2x_text_out8(tl_x, (y+=10), "Done"); diff --git a/platform/readme.txt b/platform/readme.txt index 277a89b..dcab22e 100644 --- a/platform/readme.txt +++ b/platform/readme.txt @@ -214,11 +214,12 @@ Changelog 1.2x + ISO files now can be zipped. Note that this causes VERY long loading times. + Added data pre-buffering support, this allows to reduce frequency of short pauses - in FMV games, but makes those pauses longer. + in FMV games (caused by SD access), but makes those pauses longer. * Fixed PCM DMA transfers (intro FMV in Popful Mail). + Properly implemented "decode" data transformation (Jaguar XJ220). * Integrated "better sync" code into cyclone code, what made this mode much faster. * Fixed a bug related to game specific config saving. + * Frameskipper was skipping sound processing, what caused some audio desyncs. Fixed. 1.201 + Added basic cheat support (GameGenie and Genecyst patches). -- 2.39.2