From 9037e45d9f2752fdd6ebbc01328148839403a84f Mon Sep 17 00:00:00 2001 From: notaz Date: Thu, 1 May 2008 11:27:50 +0000 Subject: [PATCH] .cue support, Pico stubs git-svn-id: file:///home/notaz/opt/svn/PicoDrive@433 be3aeb3a-fb24-0410-a615-afba39da0efa --- Pico/Cart.c | 18 +++- Pico/Memory.c | 125 ++++++++++++++------------ Pico/Pico.c | 2 +- Pico/Pico/Memory.c | 179 +++++++++++++++++++++++++++++++++++++ Pico/Pico/Pico.c | 10 +++ Pico/PicoInt.h | 13 ++- Pico/Sek.c | 2 +- Pico/cd/Memory.c | 48 ++++++++-- Pico/cd/cd_file.c | 192 +++++++++++++++++++++++++++------------- Pico/cd/cd_sys.h | 1 + Pico/cd/cue.c | 51 +++++++---- Pico/cd/cue.h | 6 +- platform/common/emu.c | 40 +++++++-- platform/gp2x/Makefile | 2 +- platform/linux/Makefile | 6 +- platform/psp/Makefile | 2 +- 16 files changed, 533 insertions(+), 164 deletions(-) create mode 100644 Pico/Pico/Memory.c create mode 100644 Pico/Pico/Pico.c diff --git a/Pico/Cart.c b/Pico/Cart.c index 1e0ce2b..1dc3eae 100644 --- a/Pico/Cart.c +++ b/Pico/Cart.c @@ -528,9 +528,14 @@ int PicoCartInsert(unsigned char *rom,unsigned int romsize) // setup correct memory map for loaded ROM // call PicoMemReset again due to possible memmap change - if (PicoAHW & PAHW_MCD) - PicoMemSetupCD(); - else PicoMemSetup(); + switch (PicoAHW) { + default: + elprintf(EL_STATUS|EL_ANOMALY, "starting in unknown hw configuration: %x", PicoAHW); + case 0: + case PAHW_SVP: PicoMemSetup(); break; + case PAHW_MCD: PicoMemSetupCD(); break; + case PAHW_PICO: PicoMemSetupPico(); break; + } PicoMemReset(); PicoPower(); @@ -674,6 +679,13 @@ static void PicoCartDetect(void) PicoSVPStartup(); } + // Pico + else if (rom_strcmp(0x100, "SEGA PICO") == 0 || + rom_strcmp(0x100, "IMA IKUNOUJYUKU") == 0) // what is that supposed to mean? + { + PicoInitPico(); + } + // Detect 12-in-1 mapper else if ((name_cmp("ROBOCOP 3") == 0 && Pico.romsize == 0x200000) || (rom_strcmp(0x160, "FLICKY") == 0 && Pico.romsize >= 0x200000) || diff --git a/Pico/Memory.c b/Pico/Memory.c index b4e473b..29f0470 100644 --- a/Pico/Memory.c +++ b/Pico/Memory.c @@ -210,6 +210,14 @@ static u32 OtherRead16End(u32 a, int realsize) { u32 d=0; + // 32x test +/* + if (a == 0xa130ec) { d = 0x4d41; goto end; } // MA + else if (a == 0xa130ee) { d = 0x5253; goto end; } // RS + else if (a == 0xa15100) { d = 0x0080; goto end; } + else +*/ + // for games with simple protection devices, discovered by Haze // some dumb detection is used, but that should be enough to make things work if ((a>>22) == 1 && Pico.romsize >= 512*1024) { @@ -488,7 +496,6 @@ static void PicoWrite32(u32 a,u32 d) // ----------------------------------------------------------------- -// TODO: asm code static void OtherWrite16End(u32 a,u32 d,int realsize) { PicoWrite8Hook(a, d>>8, realsize); @@ -507,6 +514,10 @@ PICO_INTERNAL void PicoMemResetHooks(void) PicoWrite16Hook = OtherWrite16End; } +#ifdef EMU_M68K +static void m68k_mem_setup(void); +#endif + PICO_INTERNAL void PicoMemSetup(void) { // Setup memory callbacks: @@ -530,7 +541,7 @@ PICO_INTERNAL void PicoMemSetup(void) // setup FAME fetchmap { int i; - // by default, point everything to fitst 64k of ROM + // by default, point everything to first 64k of ROM for (i = 0; i < M68K_FETCHBANK1; i++) PicoCpuFM68k.Fetch[i] = (unsigned int)Pico.rom - (i<<(24-FAMEC_FETCHBITS)); // now real ROM @@ -541,15 +552,24 @@ PICO_INTERNAL void PicoMemSetup(void) PicoCpuFM68k.Fetch[i] = (unsigned int)Pico.ram - (i<<(24-FAMEC_FETCHBITS)); } #endif +#ifdef EMU_M68K + m68k_mem_setup(); +#endif } - +/* some nasty things below :( */ #ifdef EMU_M68K -unsigned int m68k_read_pcrelative_CD8 (unsigned int a); -unsigned int m68k_read_pcrelative_CD16(unsigned int a); -unsigned int m68k_read_pcrelative_CD32(unsigned int a); - -// these are allowed to access RAM +unsigned int (*pm68k_read_memory_8) (unsigned int address) = NULL; +unsigned int (*pm68k_read_memory_16)(unsigned int address) = NULL; +unsigned int (*pm68k_read_memory_32)(unsigned int address) = NULL; +void (*pm68k_write_memory_8) (unsigned int address, unsigned char value) = NULL; +void (*pm68k_write_memory_16)(unsigned int address, unsigned short value) = NULL; +void (*pm68k_write_memory_32)(unsigned int address, unsigned int value) = NULL; +unsigned int (*pm68k_read_memory_pcr_8) (unsigned int address) = NULL; +unsigned int (*pm68k_read_memory_pcr_16)(unsigned int address) = NULL; +unsigned int (*pm68k_read_memory_pcr_32)(unsigned int address) = NULL; + +// these are here for core debugging mode static unsigned int m68k_read_8 (unsigned int a, int do_fake) { a&=0xffffff; @@ -557,9 +577,7 @@ static unsigned int m68k_read_8 (unsigned int a, int do_fake) #ifdef EMU_CORE_DEBUG if(do_fake&&((ppop&0x3f)==0x3a||(ppop&0x3f)==0x3b)) return lastread_d[lrp_mus++&15]; #endif - if(PicoAHW&1) return m68k_read_pcrelative_CD8(a); - if((a&0xe00000)==0xe00000) return *(u8 *)(Pico.ram+((a^1)&0xffff)); // Ram - return 0; + return pm68k_read_memory_pcr_8(a); } static unsigned int m68k_read_16(unsigned int a, int do_fake) { @@ -568,9 +586,7 @@ static unsigned int m68k_read_16(unsigned int a, int do_fake) #ifdef EMU_CORE_DEBUG if(do_fake&&((ppop&0x3f)==0x3a||(ppop&0x3f)==0x3b)) return lastread_d[lrp_mus++&15]; #endif - if(PicoAHW&1) return m68k_read_pcrelative_CD16(a); - if((a&0xe00000)==0xe00000) return *(u16 *)(Pico.ram+(a&0xfffe)); // Ram - return 0; + return pm68k_read_memory_pcr_16(a); } static unsigned int m68k_read_32(unsigned int a, int do_fake) { @@ -579,9 +595,7 @@ static unsigned int m68k_read_32(unsigned int a, int do_fake) #ifdef EMU_CORE_DEBUG if(do_fake&&((ppop&0x3f)==0x3a||(ppop&0x3f)==0x3b)) return lastread_d[lrp_mus++&15]; #endif - if(PicoAHW&1) return m68k_read_pcrelative_CD32(a); - if((a&0xe00000)==0xe00000) { u16 *pm=(u16 *)(Pico.ram+(a&0xfffe)); return (pm[0]<<16)|pm[1]; } // Ram - return 0; + return pm68k_read_memory_pcr_32(a); } unsigned int m68k_read_pcrelative_8 (unsigned int a) { return m68k_read_8 (a, 1); } @@ -593,6 +607,24 @@ unsigned int m68k_read_disassembler_8 (unsigned int a) { return m68k_read_8 (a, unsigned int m68k_read_disassembler_16(unsigned int a) { return m68k_read_16(a, 0); } unsigned int m68k_read_disassembler_32(unsigned int a) { return m68k_read_32(a, 0); } +static unsigned int m68k_read_memory_pcr_8(unsigned int a) +{ + if((a&0xe00000)==0xe00000) return *(u8 *)(Pico.ram+((a^1)&0xffff)); // Ram + return 0; +} + +static unsigned int m68k_read_memory_pcr_16(unsigned int a) +{ + if((a&0xe00000)==0xe00000) return *(u16 *)(Pico.ram+(a&0xfffe)); // Ram + return 0; +} + +static unsigned int m68k_read_memory_pcr_32(unsigned int a) +{ + if((a&0xe00000)==0xe00000) { u16 *pm=(u16 *)(Pico.ram+(a&0xfffe)); return (pm[0]<<16)|pm[1]; } // Ram + return 0; +} + #ifdef EMU_CORE_DEBUG // ROM only unsigned int m68k_read_memory_8(unsigned int a) @@ -628,47 +660,30 @@ unsigned int m68k_read_memory_32(unsigned int a) void m68k_write_memory_8(unsigned int address, unsigned int value) { lastwrite_mus_d[lwp_mus++&15] = value; } void m68k_write_memory_16(unsigned int address, unsigned int value) { lastwrite_mus_d[lwp_mus++&15] = value; } void m68k_write_memory_32(unsigned int address, unsigned int value) { lastwrite_mus_d[lwp_mus++&15] = value; } -#else -unsigned char PicoReadCD8w (unsigned int a); -unsigned short PicoReadCD16w(unsigned int a); -unsigned int PicoReadCD32w(unsigned int a); -void PicoWriteCD8w (unsigned int a, unsigned char d); -void PicoWriteCD16w(unsigned int a, unsigned short d); -void PicoWriteCD32w(unsigned int a, unsigned int d); - -/* it appears that Musashi doesn't always mask the unused bits */ -unsigned int m68k_read_memory_8(unsigned int address) -{ - unsigned int d = (PicoAHW&1) ? PicoReadCD8w(address) : PicoRead8(address); - return d&0xff; -} - -unsigned int m68k_read_memory_16(unsigned int address) -{ - unsigned int d = (PicoAHW&1) ? PicoReadCD16w(address) : PicoRead16(address); - return d&0xffff; -} - -unsigned int m68k_read_memory_32(unsigned int address) -{ - return (PicoAHW&1) ? PicoReadCD32w(address) : PicoRead32(address); -} - -void m68k_write_memory_8(unsigned int address, unsigned int value) -{ - if (PicoAHW&1) PicoWriteCD8w(address, (u8)value); else PicoWrite8(address, (u8)value); -} -void m68k_write_memory_16(unsigned int address, unsigned int value) -{ - if (PicoAHW&1) PicoWriteCD16w(address,(u16)value); else PicoWrite16(address,(u16)value); -} +#else // if !EMU_CORE_DEBUG -void m68k_write_memory_32(unsigned int address, unsigned int value) -{ - if (PicoAHW&1) PicoWriteCD32w(address, value); else PicoWrite32(address, value); +/* it appears that Musashi doesn't always mask the unused bits */ +unsigned int m68k_read_memory_8 (unsigned int address) { return pm68k_read_memory_8 (address) & 0xff; } +unsigned int m68k_read_memory_16(unsigned int address) { return pm68k_read_memory_16(address) & 0xffff; } +unsigned int m68k_read_memory_32(unsigned int address) { return pm68k_read_memory_32(address); } +void m68k_write_memory_8 (unsigned int address, unsigned int value) { pm68k_write_memory_8 (address, (u8)value); } +void m68k_write_memory_16(unsigned int address, unsigned int value) { pm68k_write_memory_16(address,(u16)value); } +void m68k_write_memory_32(unsigned int address, unsigned int value) { pm68k_write_memory_32(address, value); } +#endif // !EMU_CORE_DEBUG + +static void m68k_mem_setup(void) +{ + pm68k_read_memory_8 = PicoRead8; + pm68k_read_memory_16 = PicoRead16; + pm68k_read_memory_32 = PicoRead32; + pm68k_write_memory_8 = PicoWrite8; + pm68k_write_memory_16 = PicoWrite16; + pm68k_write_memory_32 = PicoWrite32; + pm68k_read_memory_pcr_8 = m68k_read_memory_pcr_8; + pm68k_read_memory_pcr_16 = m68k_read_memory_pcr_16; + pm68k_read_memory_pcr_32 = m68k_read_memory_pcr_32; } -#endif #endif // EMU_M68K diff --git a/Pico/Pico.c b/Pico/Pico.c index 7fa152a..4e34e51 100644 --- a/Pico/Pico.c +++ b/Pico/Pico.c @@ -16,7 +16,7 @@ int PicoOpt = 0; int PicoSkipFrame = 0; // skip rendering frame? int emustatus = 0; // rapid_ym2612, multi_ym_updates int PicoPad[2]; // Joypads, format is SACB RLDU -int PicoAHW = 0; // active addon hardware: scd_active, 32x_active, svp_active +int PicoAHW = 0; // active addon hardware: scd_active, 32x_active, svp_active, pico_active int PicoRegionOverride = 0; // override the region detection 0: Auto, 1: Japan NTSC, 2: Japan PAL, 4: US, 8: Europe int PicoAutoRgnOrder = 0; int z80startCycle, z80stopCycle; // in 68k cycles diff --git a/Pico/Pico/Memory.c b/Pico/Pico/Memory.c new file mode 100644 index 0000000..f1eddd0 --- /dev/null +++ b/Pico/Pico/Memory.c @@ -0,0 +1,179 @@ +#include "../PicoInt.h" + +#ifndef UTYPES_DEFINED +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; +#define UTYPES_DEFINED +#endif + +// ----------------------------------------------------------------- +// Read Rom and read Ram + +static u32 PicoReadPico8(u32 a) +{ + u32 d=0; + + if ((a&0xe00000)==0xe00000) { d = *(u8 *)(Pico.ram+((a^1)&0xffff)); goto end; } // Ram + if (a>=8; + goto end; + } + + elprintf(EL_UIO, "r8 : %06x, %02x @%06x", a&0xffffff, (u8)d, SekPc); + +end: + elprintf(EL_IO, "r8 : %06x, %02x @%06x", a&0xffffff, (u8)d, SekPc); + return d; +} + +static u32 PicoReadPico16(u32 a) +{ + u32 d=0; + + if ((a&0xe00000)==0xe00000) { d=*(u16 *)(Pico.ram+(a&0xfffe)); goto end; } // Ram + + a&=0xfffffe; + + if (a>16); pm[1]=(u16)d; + return; + } + + a&=0xfffffe; + if ((a&0xffffe0)==0xc00000) + { + // VDP: + PicoVideoWrite(a, (u16)(d>>16)); + PicoVideoWrite(a+2,(u16)d); + return; + } + + elprintf(EL_UIO, "w32: %06x, %08x", a&0xffffff, d); +} + +#ifdef EMU_M68K +extern unsigned int (*pm68k_read_memory_8) (unsigned int address); +extern unsigned int (*pm68k_read_memory_16)(unsigned int address); +extern unsigned int (*pm68k_read_memory_32)(unsigned int address); +extern void (*pm68k_write_memory_8) (unsigned int address, unsigned char value); +extern void (*pm68k_write_memory_16)(unsigned int address, unsigned short value); +extern void (*pm68k_write_memory_32)(unsigned int address, unsigned int value); +extern unsigned int (*pm68k_read_memory_pcr_8) (unsigned int address); +extern unsigned int (*pm68k_read_memory_pcr_16)(unsigned int address); +extern unsigned int (*pm68k_read_memory_pcr_32)(unsigned int address); + +static unsigned int m68k_read_memory_pcrp_8(unsigned int a) +{ + if((a&0xe00000)==0xe00000) return *(u8 *)(Pico.ram+((a^1)&0xffff)); // Ram + return 0; +} + +static unsigned int m68k_read_memory_pcrp_16(unsigned int a) +{ + if((a&0xe00000)==0xe00000) return *(u16 *)(Pico.ram+(a&0xfffe)); // Ram + return 0; +} + +static unsigned int m68k_read_memory_pcrp_32(unsigned int a) +{ + if((a&0xe00000)==0xe00000) { u16 *pm=(u16 *)(Pico.ram+(a&0xfffe)); return (pm[0]<<16)|pm[1]; } // Ram + return 0; +} +#endif // EMU_M68K + + +PICO_INTERNAL void PicoMemSetupPico(void) +{ +#ifdef EMU_M68K + pm68k_read_memory_8 = PicoReadPico8; + pm68k_read_memory_16 = PicoReadPico16; + pm68k_read_memory_32 = PicoReadPico32; + pm68k_write_memory_8 = PicoWritePico8; + pm68k_write_memory_16 = PicoWritePico16; + pm68k_write_memory_32 = PicoWritePico32; + pm68k_read_memory_pcr_8 = m68k_read_memory_pcrp_8; + pm68k_read_memory_pcr_16 = m68k_read_memory_pcrp_16; + pm68k_read_memory_pcr_32 = m68k_read_memory_pcrp_32; +#endif +} + diff --git a/Pico/Pico/Pico.c b/Pico/Pico/Pico.c new file mode 100644 index 0000000..fb4a3da --- /dev/null +++ b/Pico/Pico/Pico.c @@ -0,0 +1,10 @@ +#include "../PicoInt.h" + +PICO_INTERNAL int PicoInitPico(void) +{ + elprintf(EL_STATUS, "Pico detected"); + PicoAHW = PAHW_PICO; + + return 0; +} + diff --git a/Pico/PicoInt.h b/Pico/PicoInt.h index dea4b02..aa61648 100644 --- a/Pico/PicoInt.h +++ b/Pico/PicoInt.h @@ -212,9 +212,10 @@ extern struct DrZ80 drZ80; // --------------------------------------------------------- // Pico active hw -#define PAHW_MCD (1<<0) -#define PAHW_32X (1<<1) -#define PAHW_SVP (1<<2) +#define PAHW_MCD (1<<0) +#define PAHW_32X (1<<1) +#define PAHW_SVP (1<<2) +#define PAHW_PICO (1<<3) extern int PicoAHW; // main oscillator clock which controls timing @@ -420,6 +421,9 @@ PICO_INTERNAL void PicoMemSetupCD(void); PICO_INTERNAL_ASM void PicoMemResetCD(int r3); PICO_INTERNAL_ASM void PicoMemResetCDdecode(int r3); +// Pico/Memory.c +PICO_INTERNAL void PicoMemSetupPico(void); + // Pico.c extern struct Pico Pico; extern struct PicoSRAM SRam; @@ -436,6 +440,9 @@ PICO_INTERNAL void PicoPowerMCD(void); PICO_INTERNAL int PicoResetMCD(void); PICO_INTERNAL int PicoFrameMCD(void); +// Pico/Pico.c +PICO_INTERNAL int PicoInitPico(void); + // Sek.c PICO_INTERNAL int SekInit(void); PICO_INTERNAL int SekReset(void); diff --git a/Pico/Sek.c b/Pico/Sek.c index 7ebb930..84d7807 100644 --- a/Pico/Sek.c +++ b/Pico/Sek.c @@ -114,7 +114,7 @@ PICO_INTERNAL int SekInit() m68k_init(); m68k_set_int_ack_callback(SekIntAckM68K); m68k_set_tas_instr_callback(SekTasCallback); - m68k_pulse_reset(); // Init cpu emulator + //m68k_pulse_reset(); m68k_set_context(oldcontext); } #endif diff --git a/Pico/cd/Memory.c b/Pico/cd/Memory.c index b1faacd..2b419b7 100644 --- a/Pico/cd/Memory.c +++ b/Pico/cd/Memory.c @@ -1636,6 +1636,10 @@ void PicoMemResetCD(int r3) } #endif +#ifdef EMU_M68K +static void m68k_mem_setup_cd(void); +#endif + PICO_INTERNAL void PicoMemSetupCD(void) { // additional handlers for common code @@ -1702,6 +1706,9 @@ PICO_INTERNAL void PicoMemSetupCD(void) // PicoMemResetCD() will setup word ram for both } #endif +#ifdef EMU_M68K + m68k_mem_setup_cd(); +#endif // m68k_poll_addr = m68k_poll_cnt = 0; s68k_poll_adclk = s68k_poll_cnt = 0; @@ -1709,27 +1716,27 @@ PICO_INTERNAL void PicoMemSetupCD(void) #ifdef EMU_M68K -unsigned char PicoReadCD8w (unsigned int a) { +static unsigned int PicoReadCD8w (unsigned int a) { return m68ki_cpu_p == &PicoCpuMS68k ? PicoReadS68k8(a) : PicoReadM68k8(a); } -unsigned short PicoReadCD16w(unsigned int a) { +static unsigned int PicoReadCD16w(unsigned int a) { return m68ki_cpu_p == &PicoCpuMS68k ? PicoReadS68k16(a) : PicoReadM68k16(a); } -unsigned int PicoReadCD32w(unsigned int a) { +static unsigned int PicoReadCD32w(unsigned int a) { return m68ki_cpu_p == &PicoCpuMS68k ? PicoReadS68k32(a) : PicoReadM68k32(a); } -void PicoWriteCD8w (unsigned int a, unsigned char d) { +static void PicoWriteCD8w (unsigned int a, unsigned char d) { if (m68ki_cpu_p == &PicoCpuMS68k) PicoWriteS68k8(a, d); else PicoWriteM68k8(a, d); } -void PicoWriteCD16w(unsigned int a, unsigned short d) { +static void PicoWriteCD16w(unsigned int a, unsigned short d) { if (m68ki_cpu_p == &PicoCpuMS68k) PicoWriteS68k16(a, d); else PicoWriteM68k16(a, d); } -void PicoWriteCD32w(unsigned int a, unsigned int d) { +static void PicoWriteCD32w(unsigned int a, unsigned int d) { if (m68ki_cpu_p == &PicoCpuMS68k) PicoWriteS68k32(a, d); else PicoWriteM68k32(a, d); } // these are allowed to access RAM -unsigned int m68k_read_pcrelative_CD8 (unsigned int a) +static unsigned int m68k_read_pcrelative_CD8 (unsigned int a) { a&=0xffffff; if(m68ki_cpu_p == &PicoCpuMS68k) { @@ -1756,7 +1763,7 @@ unsigned int m68k_read_pcrelative_CD8 (unsigned int a) } return 0;//(u8) lastread_d; } -unsigned int m68k_read_pcrelative_CD16(unsigned int a) +static unsigned int m68k_read_pcrelative_CD16(unsigned int a) { a&=0xffffff; if(m68ki_cpu_p == &PicoCpuMS68k) { @@ -1783,7 +1790,7 @@ unsigned int m68k_read_pcrelative_CD16(unsigned int a) } return 0; } -unsigned int m68k_read_pcrelative_CD32(unsigned int a) +static unsigned int m68k_read_pcrelative_CD32(unsigned int a) { u16 *pm; a&=0xffffff; @@ -1813,5 +1820,28 @@ unsigned int m68k_read_pcrelative_CD32(unsigned int a) } return 0; } + +extern unsigned int (*pm68k_read_memory_8) (unsigned int address); +extern unsigned int (*pm68k_read_memory_16)(unsigned int address); +extern unsigned int (*pm68k_read_memory_32)(unsigned int address); +extern void (*pm68k_write_memory_8) (unsigned int address, unsigned char value); +extern void (*pm68k_write_memory_16)(unsigned int address, unsigned short value); +extern void (*pm68k_write_memory_32)(unsigned int address, unsigned int value); +extern unsigned int (*pm68k_read_memory_pcr_8) (unsigned int address); +extern unsigned int (*pm68k_read_memory_pcr_16)(unsigned int address); +extern unsigned int (*pm68k_read_memory_pcr_32)(unsigned int address); + +static void m68k_mem_setup_cd(void) +{ + pm68k_read_memory_8 = PicoReadCD8w; + pm68k_read_memory_16 = PicoReadCD16w; + pm68k_read_memory_32 = PicoReadCD32w; + pm68k_write_memory_8 = PicoWriteCD8w; + pm68k_write_memory_16 = PicoWriteCD16w; + pm68k_write_memory_32 = PicoWriteCD32w; + pm68k_read_memory_pcr_8 = m68k_read_pcrelative_CD8; + pm68k_read_memory_pcr_16 = m68k_read_pcrelative_CD16; + pm68k_read_memory_pcr_32 = m68k_read_pcrelative_CD32; +} #endif // EMU_M68K diff --git a/Pico/cd/cd_file.c b/Pico/cd/cd_file.c index 895a75f..549aab9 100644 --- a/Pico/cd/cd_file.c +++ b/Pico/cd/cd_file.c @@ -9,15 +9,61 @@ #include "../PicoInt.h" #include "cd_file.h" +#include "cue.h" //#define cdprintf(f,...) printf(f "\n",##__VA_ARGS__) // tmp -#define DEBUG_CD -PICO_INTERNAL int Load_CD_Image(const char *iso_name, cd_img_type type) +static int audio_track_mp3(const char *fname, int index) { - int i, j, num_track, Cur_LBA, index, ret, iso_name_len; + _scd_track *Tracks = Pico_mcd->TOC.Tracks; + FILE *tmp_file; + int fs, ret; + + tmp_file = fopen(fname, "rb"); + if (tmp_file == NULL) + return -1; + + ret = fseek(tmp_file, 0, SEEK_END); + fs = ftell(tmp_file); // used to calculate length + fseek(tmp_file, 0, SEEK_SET); + +#if DONT_OPEN_MANY_FILES + // some systems (like PSP) can't have many open files at a time, + // so we work with their names instead. + fclose(tmp_file); + tmp_file = (void *) strdup(fname); +#endif + Tracks[index].KBtps = (short) mp3_get_bitrate(tmp_file, fs); + Tracks[index].KBtps >>= 3; + if (ret != 0 || Tracks[index].KBtps <= 0) + { + elprintf(EL_STATUS, "track %2i: mp3 bitrate %i", index+1, Tracks[index].KBtps); +#if !DONT_OPEN_MANY_FILES + fclose(tmp_file); +#else + free(tmp_file); +#endif + return -1; + } + + Tracks[index].F = tmp_file; + + // MP3 File + Tracks[index].ftype = TYPE_MP3; + fs *= 75; + fs /= Tracks[index].KBtps * 1000; + Tracks[index].Length = fs; + Tracks[index].Offset = 0; + + return 0; +} + +PICO_INTERNAL int Load_CD_Image(const char *cd_img_name, cd_img_type type) +{ + int i, j, num_track, Cur_LBA, index, ret, iso_name_len, missed, cd_img_sectors; _scd_track *Tracks = Pico_mcd->TOC.Tracks; char tmp_name[1024], tmp_ext[10]; + cue_data_t *cue_data = NULL; pm_file *pmf; static char *exts[] = { "%02d.mp3", " %02d.mp3", "-%02d.mp3", "_%02d.mp3", " - %02d.mp3", @@ -31,109 +77,134 @@ PICO_INTERNAL int Load_CD_Image(const char *iso_name, cd_img_type type) Unload_ISO(); + /* is this .cue? */ + ret = strlen(cd_img_name); + if (ret >= 3 && strcasecmp(cd_img_name + ret - 3, "cue") == 0) + cue_data = cue_parse(cd_img_name); + if (cue_data != NULL) + cd_img_name = cue_data->tracks[1].fname; + Tracks[0].ftype = type == CIT_BIN ? TYPE_BIN : TYPE_ISO; - Tracks[0].F = pmf = pm_open(iso_name); + Tracks[0].F = pmf = pm_open(cd_img_name); if (Tracks[0].F == NULL) { Tracks[0].ftype = 0; Tracks[0].Length = 0; + if (cue_data != NULL) + cue_destroy(cue_data); return -1; } if (Tracks[0].ftype == TYPE_ISO) - Tracks[0].Length = pmf->size >>= 11; // size in sectors - else Tracks[0].Length = pmf->size /= 2352; + cd_img_sectors = pmf->size >>= 11; // size in sectors + else cd_img_sectors = pmf->size /= 2352; + Tracks[0].Offset = 0; Tracks[0].MSF.M = 0; // minutes Tracks[0].MSF.S = 2; // seconds Tracks[0].MSF.F = 0; // frames - cdprintf("Track 0 - %02d:%02d:%02d DATA", Tracks[0].MSF.M, Tracks[0].MSF.S, Tracks[0].MSF.F); + elprintf(EL_STATUS, "Track 0: %02d:%02d:%02d %9i DATA", + Tracks[0].MSF.M, Tracks[0].MSF.S, Tracks[0].MSF.F, Tracks[0].Length); + + Cur_LBA = Tracks[0].Length = cd_img_sectors; + + if (cue_data != NULL) + { + if (cue_data->tracks[2].fname == NULL) { // NULL means track2 is in same file as track1 + Cur_LBA = Tracks[0].Length = cue_data->tracks[2].sector_offset; + } + for (num_track = 2; num_track <= cue_data->track_count; num_track++) + { + index = num_track - 1; + Cur_LBA += cue_data->tracks[num_track].pregap; + if (cue_data->tracks[num_track].type == CT_MP3) { + ret = audio_track_mp3(cue_data->tracks[num_track].fname, index); + if (ret != 0) break; + } + else + { + Tracks[index].ftype = cue_data->tracks[num_track].type; + if (cue_data->tracks[num_track].fname != NULL) + { + Tracks[index].F = fopen(cue_data->tracks[num_track].fname, "rb"); + elprintf(EL_STATUS, "track %2i (%s): can't determine length", + cue_data->tracks[num_track].fname); + Tracks[index].Length = 2*75; + Tracks[index].Offset = 0; + } else { + if (num_track < cue_data->track_count) + Tracks[index].Length = cue_data->tracks[num_track+1].sector_offset - + cue_data->tracks[num_track].sector_offset; + else + Tracks[index].Length = cd_img_sectors - cue_data->tracks[num_track].sector_offset; + Tracks[index].Offset = cue_data->tracks[num_track].sector_offset; + } + } + + LBA_to_MSF(Cur_LBA, &Tracks[index].MSF); + Cur_LBA += Tracks[index].Length; - Cur_LBA = Tracks[0].Length; // Size in sectors + elprintf(EL_STATUS, "Track %2i: %02d:%02d:%02d %9i AUDIO - %s", index, Tracks[index].MSF.M, + Tracks[index].MSF.S, Tracks[index].MSF.F, Tracks[index].Length, + cue_data->tracks[num_track].fname); + } + cue_destroy(cue_data); + goto finish; + } - iso_name_len = strlen(iso_name); + /* track autosearch, Gens-like */ + iso_name_len = strlen(cd_img_name); if (iso_name_len >= sizeof(tmp_name)) iso_name_len = sizeof(tmp_name) - 1; - for (num_track = 2, i = 0; i < 100; i++) + for (num_track = 2, i = 0, missed = 0; i < 100 && missed < 4; i++) { - if (PicoCDLoadProgressCB != NULL && i > 1) PicoCDLoadProgressCB(i); + if (PicoCDLoadProgressCB != NULL && i > 1) PicoCDLoadProgressCB(i + (100-i)*missed/4); for (j = 0; j < sizeof(exts)/sizeof(char *); j++) { int ext_len; - FILE *tmp_file; sprintf(tmp_ext, exts[j], i); ext_len = strlen(tmp_ext); - memcpy(tmp_name, iso_name, iso_name_len + 1); + memcpy(tmp_name, cd_img_name, iso_name_len + 1); tmp_name[iso_name_len - 4] = 0; strcat(tmp_name, tmp_ext); - tmp_file = fopen(tmp_name, "rb"); - if (!tmp_file && i > 1 && iso_name_len > ext_len) { + index = num_track - 1; + ret = audio_track_mp3(tmp_name, index); + if (ret != 0 && i > 1 && iso_name_len > ext_len) { tmp_name[iso_name_len - ext_len] = 0; strcat(tmp_name, tmp_ext); - tmp_file = fopen(tmp_name, "rb"); + ret = audio_track_mp3(tmp_name, index); } - if (tmp_file) + if (ret == 0) { - int fs; - index = num_track - 1; - - ret = fseek(tmp_file, 0, SEEK_END); - fs = ftell(tmp_file); // used to calculate lenght - fseek(tmp_file, 0, SEEK_SET); - -#if DONT_OPEN_MANY_FILES - // some systems (like PSP) can't have many open files at a time, - // so we work with their names instead. - fclose(tmp_file); - tmp_file = (void *) strdup(tmp_name); -#endif - Tracks[index].KBtps = (short) mp3_get_bitrate(tmp_file, fs); - Tracks[index].KBtps >>= 3; - if (ret != 0 || Tracks[index].KBtps <= 0) - { - cdprintf("Error track %i: rate %i", index, Tracks[index].KBtps); -#if !DONT_OPEN_MANY_FILES - fclose(tmp_file); -#else - free(tmp_file); -#endif - continue; - } - - Tracks[index].F = tmp_file; - LBA_to_MSF(Cur_LBA, &Tracks[index].MSF); - - // MP3 File - Tracks[index].ftype = TYPE_MP3; - fs *= 75; - fs /= Tracks[index].KBtps * 1000; - Tracks[index].Length = fs; Cur_LBA += Tracks[index].Length; - cdprintf("Track %i: %s - %02d:%02d:%02d len=%i AUDIO", index, tmp_name, Tracks[index].MSF.M, - Tracks[index].MSF.S, Tracks[index].MSF.F, fs); + elprintf(EL_STATUS, "Track %2i: %02d:%02d:%02d %9i AUDIO - %s", index, Tracks[index].MSF.M, + Tracks[index].MSF.S, Tracks[index].MSF.F, Tracks[index].Length, tmp_name); num_track++; + missed = 0; break; } } + if (ret != 0) missed++; } +finish: Pico_mcd->TOC.Last_Track = num_track - 1; index = num_track - 1; LBA_to_MSF(Cur_LBA, &Tracks[index].MSF); - cdprintf("End CD - %02d:%02d:%02d\n\n", Tracks[index].MSF.M, + elprintf(EL_STATUS, "End CD - %02d:%02d:%02d\n", Tracks[index].MSF.M, Tracks[index].MSF.S, Tracks[index].MSF.F); if (PicoCDLoadProgressCB != NULL) PicoCDLoadProgressCB(100); @@ -153,11 +224,14 @@ PICO_INTERNAL void Unload_ISO(void) for(i = 1; i < 100; i++) { if (Pico_mcd->TOC.Tracks[i].F != NULL) -#if !DONT_OPEN_MANY_FILES - fclose(Pico_mcd->TOC.Tracks[i].F); -#else - free(Pico_mcd->TOC.Tracks[i].F); + { +#if DONT_OPEN_MANY_FILES + if (Pico_mcd->TOC.Tracks[i].type == TYPE_MP3) + free(Pico_mcd->TOC.Tracks[i].F); + else #endif + fclose(Pico_mcd->TOC.Tracks[i].F); + } } memset(Pico_mcd->TOC.Tracks, 0, sizeof(Pico_mcd->TOC.Tracks)); } @@ -223,7 +297,6 @@ PICO_INTERNAL int FILE_Read_One_LBA_CDC(void) //pm_read(Pico_mcd->cdc.Buffer + Pico_mcd->cdc.PT.N + 4, 2048, Pico_mcd->TOC.Tracks[0].F); PicoCDBufferRead(Pico_mcd->cdc.Buffer + Pico_mcd->cdc.PT.N + 4, where_read); -#ifdef DEBUG_CD cdprintf("Read -> WA = %d Buffer[%d] =", Pico_mcd->cdc.WA.N, Pico_mcd->cdc.PT.N & 0x3FFF); cdprintf("Header 1 = %.2X %.2X %.2X %.2X", Pico_mcd->cdc.HEAD.B.B0, Pico_mcd->cdc.HEAD.B.B1, Pico_mcd->cdc.HEAD.B.B2, Pico_mcd->cdc.HEAD.B.B3); @@ -234,7 +307,6 @@ PICO_INTERNAL int FILE_Read_One_LBA_CDC(void) Pico_mcd->cdc.Buffer[(Pico_mcd->cdc.PT.N + 3) & 0x3FFF], Pico_mcd->cdc.Buffer[(Pico_mcd->cdc.PT.N + 4) & 0x3FFF], Pico_mcd->cdc.Buffer[(Pico_mcd->cdc.PT.N + 5) & 0x3FFF]); -#endif } } diff --git a/Pico/cd/cd_sys.h b/Pico/cd/cd_sys.h index 77a9f06..6725efc 100644 --- a/Pico/cd/cd_sys.h +++ b/Pico/cd/cd_sys.h @@ -46,6 +46,7 @@ typedef struct char ftype; // TYPE_ISO, TYPE_BIN, TYPE_MP3 void *F; int Length; + int Offset; // sector offset, when single file is used for multiple virtual tracks short KBtps; // kbytes per sec for mp3s (bitrate / 1000 / 8) short pad; } _scd_track; diff --git a/Pico/cd/cue.c b/Pico/cd/cue.c index 2ef320b..3380b0e 100644 --- a/Pico/cd/cue.c +++ b/Pico/cd/cue.c @@ -3,8 +3,8 @@ #include #include "cue.h" -//#include "../PicoInt.h" -#define elprintf(w,f,...) printf(f "\n",##__VA_ARGS__); +#include "../PicoInt.h" +// #define elprintf(w,f,...) printf(f "\n",##__VA_ARGS__); static char *mystrip(char *str) { @@ -42,7 +42,7 @@ static int get_token(const char *buff, char *dest, int len) dest[d++] = *p++; dest[d] = 0; - if (*p != sep) + if (sep == '\"' && *p != sep) elprintf(EL_STATUS, "cue: bad token: \"%s\"", buff); return d + skip; @@ -51,19 +51,19 @@ static int get_token(const char *buff, char *dest, int len) static char *get_ext(char *fname) { int len = strlen(fname); - return (len >= 3) ? (fname - 3) : (fname - len); + return (len >= 3) ? (fname + len - 3) : fname; } #define BEGINS(buff,str) (strncmp(buff,str,sizeof(str)-1) == 0) /* note: tracks[0] is not used */ -cue_data *cue_parse(const char *fname) +cue_data_t *cue_parse(const char *fname) { char buff[256], current_file[256], buff2[32]; FILE *f, *tmpf; int ret, count = 0, count_alloc = 2; - cue_data *data; + cue_data_t *data; void *tmp; f = fopen(fname, "r"); @@ -92,6 +92,7 @@ cue_data *cue_parse(const char *fname) count_alloc *= 2; tmp = realloc(data, sizeof(*data) + count_alloc * sizeof(cue_track)); if (tmp == NULL) { count--; break; } + data = tmp; } memset(&data->tracks[count], 0, sizeof(data->tracks[0])); if (count == 1 || strcmp(data->tracks[1].fname, current_file) != 0) @@ -113,11 +114,11 @@ cue_data *cue_parse(const char *fname) count, atoi(buff2)); // check type get_token(buff+6+ret, buff2, sizeof(buff2)); - if (strcmp(buff2, "MODE1/2352")) + if (strcmp(buff2, "MODE1/2352") == 0) data->tracks[count].type = CT_BIN; - else if (strcmp(buff2, "MODE1/2048")) + else if (strcmp(buff2, "MODE1/2048") == 0) data->tracks[count].type = CT_ISO; - else if (strcmp(buff2, "AUDIO")) + else if (strcmp(buff2, "AUDIO") == 0) { if (data->tracks[count].fname != NULL) { @@ -132,6 +133,11 @@ cue_data *cue_parse(const char *fname) data->tracks[count].fname); } } + else + { + // propagate previous + data->tracks[count].type = data->tracks[count-1].type; + } } else { elprintf(EL_STATUS, "unhandled track type: \"%s\"", buff2); @@ -149,18 +155,28 @@ cue_data *cue_parse(const char *fname) } // offset in file get_token(buff+6+ret, buff2, sizeof(buff2)); - ret = sscanf(buff2, "%i:%i:%i", &m, &s, &f); + ret = sscanf(buff2, "%d:%d:%d", &m, &s, &f); if (ret != 3) { elprintf(EL_STATUS, "cue: failed to parse: \"%s\"", buff); count--; break; } data->tracks[count].sector_offset = m*60*75 + s*75 + f; + // some strange .cues may need this + if (data->tracks[count].fname != NULL && strcmp(data->tracks[count].fname, current_file) != 0) + { + free(data->tracks[count].fname); + data->tracks[count].fname = strdup(current_file); + } + if (data->tracks[count].fname == NULL && strcmp(data->tracks[1].fname, current_file) != 0) + { + data->tracks[count].fname = strdup(current_file); + } } else if (BEGINS(buff, "PREGAP ")) { int m, s, f; get_token(buff+7, buff2, sizeof(buff2)); - ret = sscanf(buff2, "%i:%i:%i", &m, &s, &f); + ret = sscanf(buff2, "%d:%d:%d", &m, &s, &f); if (ret != 3) { elprintf(EL_STATUS, "cue: failed to parse: \"%s\"", buff); continue; @@ -169,7 +185,7 @@ cue_data *cue_parse(const char *fname) } else { - elprintf(EL_STATUS, "cue: failed to parse: \"%s\"", buff); + elprintf(EL_STATUS, "cue: unhandled line: \"%s\"", buff); } } @@ -187,7 +203,7 @@ cue_data *cue_parse(const char *fname) } -void cue_destroy(cue_data *data) +void cue_destroy(cue_data_t *data) { int c; @@ -200,19 +216,22 @@ void cue_destroy(cue_data *data) } +#if 0 int main(int argc, char *argv[]) { - cue_data *data = cue_parse(argv[1]); + cue_data_t *data = cue_parse(argv[1]); int c; if (data == NULL) return 1; for (c = 1; c <= data->track_count; c++) - printf("%2i: %i %9i %9i %s\n", c, data->tracks[c].type, data->tracks[c].sector_offset, - data->tracks[c].pregap, data->tracks[c].fname); + printf("%2i: %i %9i %02i:%02i:%02i %9i %s\n", c, data->tracks[c].type, data->tracks[c].sector_offset, + data->tracks[c].sector_offset / (75*60), data->tracks[c].sector_offset / 75 % 60, + data->tracks[c].sector_offset % 75, data->tracks[c].pregap, data->tracks[c].fname); cue_destroy(data); return 0; } +#endif diff --git a/Pico/cd/cue.h b/Pico/cd/cue.h index 0c4b183..f377aa3 100644 --- a/Pico/cd/cue.h +++ b/Pico/cd/cue.h @@ -20,9 +20,9 @@ typedef struct { int track_count; cue_track tracks[0]; -} cue_data; +} cue_data_t; -cue_data *cue_parse(const char *fname); -void cue_destroy(cue_data *data); +cue_data_t *cue_parse(const char *fname); +void cue_destroy(cue_data_t *data); diff --git a/platform/common/emu.c b/platform/common/emu.c index 1bbdf35..e88859b 100644 --- a/platform/common/emu.c +++ b/platform/common/emu.c @@ -18,6 +18,7 @@ #include #include +#include #include #if defined(__GP2X__) @@ -163,12 +164,24 @@ int emu_cdCheck(int *pregion) { unsigned char buf[32]; pm_file *cd_f; - int type = 0, region = 4; // 1: Japan, 4: US, 8: Europe - char ext[5]; + int region = 4; // 1: Japan, 4: US, 8: Europe + char ext[5], *fname = romFileName; + cue_track_type type = CT_UNKNOWN; + cue_data_t *cue_data = NULL; get_ext(romFileName, ext); + if (strcasecmp(ext, ".cue") == 0) { + cue_data = cue_parse(romFileName); + if (cue_data != NULL) { + fname = cue_data->tracks[1].fname; + type = cue_data->tracks[1].type; + } + } + + cd_f = pm_open(fname); + if (cue_data != NULL) + cue_destroy(cue_data); - cd_f = pm_open(romFileName); if (!cd_f) return 0; // let the upper level handle this if (pm_read(buf, 32, cd_f) != 32) { @@ -176,18 +189,27 @@ int emu_cdCheck(int *pregion) return 0; } - if (!strncasecmp("SEGADISCSYSTEM", (char *)buf+0x00, 14)) type = 1; // Sega CD (ISO) - if (!strncasecmp("SEGADISCSYSTEM", (char *)buf+0x10, 14)) type = 2; // Sega CD (BIN) - if (type == 0) { + if (!strncasecmp("SEGADISCSYSTEM", (char *)buf+0x00, 14)) { + if (type && type != CT_ISO) + elprintf(EL_STATUS, ".cue has wrong type: %i", type); + type = CT_ISO; // Sega CD (ISO) + } + if (!strncasecmp("SEGADISCSYSTEM", (char *)buf+0x10, 14)) { + if (type && type != CT_BIN) + elprintf(EL_STATUS, ".cue has wrong type: %i", type); + type = CT_BIN; // Sega CD (BIN) + } + + if (type == CT_UNKNOWN) { pm_close(cd_f); return 0; } - pm_seek(cd_f, (type == 1) ? 0x100 : 0x110, SEEK_SET); + pm_seek(cd_f, (type == CT_ISO) ? 0x100 : 0x110, SEEK_SET); pm_read(id_header, sizeof(id_header), cd_f); /* it seems we have a CD image here. Try to detect region now.. */ - pm_seek(cd_f, (type == 1) ? 0x100+0x10B : 0x110+0x10B, SEEK_SET); + pm_seek(cd_f, (type == CT_ISO) ? 0x100+0x10B : 0x110+0x10B, SEEK_SET); pm_read(buf, 1, cd_f); pm_close(cd_f); @@ -195,7 +217,7 @@ int emu_cdCheck(int *pregion) if (buf[0] == 0xa1) region = 1; // JAP lprintf("detected %s Sega/Mega CD image with %s region\n", - type == 2 ? "BIN" : "ISO", region != 4 ? (region == 8 ? "EU" : "JAP") : "USA"); + type == CT_BIN ? "BIN" : "ISO", region != 4 ? (region == 8 ? "EU" : "JAP") : "USA"); if (pregion != NULL) *pregion = region; diff --git a/platform/gp2x/Makefile b/platform/gp2x/Makefile index 3ca1351..203b9ca 100644 --- a/platform/gp2x/Makefile +++ b/platform/gp2x/Makefile @@ -70,7 +70,7 @@ OBJS += ../../Pico/Area.o ../../Pico/Cart.o ../../Pico/Memory.o ../../Pico/Misc. ../../Pico/Patch.o # Pico - CD OBJS += ../../Pico/cd/Pico.o ../../Pico/cd/Memory.o ../../Pico/cd/Sek.o ../../Pico/cd/LC89510.o \ - ../../Pico/cd/cd_sys.o ../../Pico/cd/cd_file.o ../../Pico/cd/gfx_cd.o \ + ../../Pico/cd/cd_sys.o ../../Pico/cd/cd_file.o ../../Pico/cd/cue.o ../../Pico/cd/gfx_cd.o \ ../../Pico/cd/Area.o ../../Pico/cd/Misc.o ../../Pico/cd/pcm.o ../../Pico/cd/buffering.o endif # Pico - carthw diff --git a/platform/linux/Makefile b/platform/linux/Makefile index 5e7d9ff..5cde7f6 100644 --- a/platform/linux/Makefile +++ b/platform/linux/Makefile @@ -39,8 +39,10 @@ OBJS += Pico/Area.o Pico/Cart.o Pico/Memory.o Pico/Misc.o Pico/Pico.o Pico/Sek.o Pico/VideoPort.o Pico/Draw2.o Pico/Draw.o Pico/Patch.o # Pico - CD OBJS += Pico/cd/Pico.o Pico/cd/Memory.o Pico/cd/Sek.o Pico/cd/LC89510.o \ - Pico/cd/cd_sys.o Pico/cd/cd_file.o Pico/cd/gfx_cd.o \ + Pico/cd/cd_sys.o Pico/cd/cd_file.o Pico/cd/cue.o Pico/cd/gfx_cd.o \ Pico/cd/Area.o Pico/cd/Misc.o Pico/cd/pcm.o Pico/cd/buffering.o +# Pico - Pico +OBJS += Pico/Pico/Pico.o Pico/Pico/Memory.o # Pico - sound OBJS += Pico/sound/sound.o Pico/sound/sn76496.o Pico/sound/ym2612.o Pico/sound/mix.o # Pico - carthw @@ -77,7 +79,7 @@ endif endif vpath %.c = ../.. -DIRS = platform platform/gp2x platform/common Pico Pico/cd Pico/sound Pico/carthw/svp \ +DIRS = platform platform/gp2x platform/common Pico Pico/cd Pico/Pico Pico/sound Pico/carthw/svp \ zlib unzip cpu cpu/musashi cpu/fame cpu/mz80 cpu/cz80 all: mkdirs PicoDrive diff --git a/platform/psp/Makefile b/platform/psp/Makefile index 25a0a01..a2f37f0 100644 --- a/platform/psp/Makefile +++ b/platform/psp/Makefile @@ -38,7 +38,7 @@ OBJS += ../../Pico/Area.o ../../Pico/Cart.o ../../Pico/Memory.o ../../Pico/Misc. ../../Pico/Patch.o ../../Pico/Draw_amips.o ../../Pico/Memory_amips.o ../../Pico/Misc_amips.o # Pico - CD OBJS += ../../Pico/cd/Pico.o ../../Pico/cd/Memory.o ../../Pico/cd/Sek.o ../../Pico/cd/LC89510.o \ - ../../Pico/cd/cd_sys.o ../../Pico/cd/cd_file.o ../../Pico/cd/gfx_cd.o \ + ../../Pico/cd/cd_sys.o ../../Pico/cd/cd_file.o ../../Pico/cd/cue.o ../../Pico/cd/gfx_cd.o \ ../../Pico/cd/Area.o ../../Pico/cd/Misc.o ../../Pico/cd/pcm.o ../../Pico/cd/buffering.o # Pico - carthw OBJS += ../../Pico/carthw/carthw.o ../../Pico/carthw/svp/svp.o ../../Pico/carthw/svp/Memory.o \ -- 2.39.2