From 6059831ec738370187b4a7c3dd7c1ef1ffb7eee0 Mon Sep 17 00:00:00 2001 From: Flyinghead Date: Tue, 30 Jul 2019 19:04:51 +0200 Subject: [PATCH] reios fixes --- core/cfg/cl.cpp | 2 +- core/hw/flashrom/flashrom.h | 8 +- core/hw/gdrom/gdrom_response.cpp | 8 +- core/hw/gdrom/gdromv3.cpp | 138 ++++---- core/hw/gdrom/gdromv3.h | 19 ++ core/hw/holly/sb_mem.cpp | 21 +- core/hw/sh4/sh4_mem.h | 2 +- core/imgread/ImgReader.cpp | 34 +- core/nullDC.cpp | 7 +- core/reios/gdrom_hle.cpp | 333 ++++++++++++++---- core/reios/gdrom_hle.h | 54 +-- core/reios/iso9660.h | 557 +++++++++++++++++++++++++++++++ core/reios/reios.cpp | 335 ++++++++++--------- core/reios/reios.h | 4 +- core/reios/reios_elf.cpp | 44 +-- core/rend/gui.cpp | 4 + core/serialize.cpp | 9 +- core/types.h | 2 +- 18 files changed, 1181 insertions(+), 400 deletions(-) create mode 100644 core/reios/iso9660.h diff --git a/core/cfg/cl.cpp b/core/cfg/cl.cpp index 8d39747f5..e74c8006f 100644 --- a/core/cfg/cl.cpp +++ b/core/cfg/cl.cpp @@ -141,7 +141,7 @@ bool ParseCommandLine(int argc,wchar* argv[]) else if (extension && stricmp(extension, ".elf") == 0) { INFO_LOG(COMMON, "Using '%s' as reios elf file", *arg); - cfgSetVirtual("config", "reios.enabled", "1"); + cfgSetVirtual("config", "bios.UseReios", "yes"); cfgSetVirtual("reios", "ElfFile", *arg); } else diff --git a/core/hw/flashrom/flashrom.h b/core/hw/flashrom/flashrom.h index 078a44069..a04d185b1 100644 --- a/core/hw/flashrom/flashrom.h +++ b/core/hw/flashrom/flashrom.h @@ -411,7 +411,7 @@ struct DCFlashChip : MemChip int WriteBlock(u32 part_id, u32 block_id, const void *data) { int offset, size; - partition_info(part_id, &offset, &size); + GetPartitionInfo(part_id, &offset, &size); if (!validate_header(offset, part_id)) return 0; @@ -448,7 +448,7 @@ struct DCFlashChip : MemChip int ReadBlock(u32 part_id, u32 block_id, void *data) { int offset, size; - partition_info(part_id, &offset, &size); + GetPartitionInfo(part_id, &offset, &size); if (!validate_header(offset, part_id)) return 0; @@ -462,8 +462,7 @@ struct DCFlashChip : MemChip return 1; } -private: - void partition_info(int part_id, int *offset, int *size) + void GetPartitionInfo(int part_id, int *offset, int *size) { switch (part_id) { @@ -493,6 +492,7 @@ private: } } +private: int crc_block(struct flash_user_block *block) { const u8 *buf = (const u8 *)block; diff --git a/core/hw/gdrom/gdrom_response.cpp b/core/hw/gdrom/gdrom_response.cpp index d04df885a..1389884f7 100644 --- a/core/hw/gdrom/gdrom_response.cpp +++ b/core/hw/gdrom/gdrom_response.cpp @@ -16,12 +16,6 @@ u16 reply_a1[] = 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000 }; -u16 reply_11[] = -{ - 0x0000,0x0000,0xb400,0x0019,0x0800,0x4553,0x2020,0x2020, - 0x2020,0x6552,0x2076,0x2e36,0x3334,0x3939,0x3430,0x3830 -}; - u16 reply_71[] = { 0x0b96,0xf045,0xff7e,0x063d,0x7d4d,0xbf10,0x0007,0xcf73,0x009c,0x0cbc,0xaf1c,0x301c,0xa7e7,0xa803,0x0098,0x0fbd,0x5bbd,0x50aa,0x3923, @@ -65,4 +59,4 @@ char szExDT[8][32] = "Mode2-Form2", "Mode2-Non-XA", "-> GD UNKNOWN TYPE <=" -}; \ No newline at end of file +}; diff --git a/core/hw/gdrom/gdromv3.cpp b/core/hw/gdrom/gdromv3.cpp index 351b98ded..235da21ac 100644 --- a/core/hw/gdrom/gdromv3.cpp +++ b/core/hw/gdrom/gdromv3.cpp @@ -58,6 +58,7 @@ u32 data_write_mode=0; ByteCount_t ByteCount; //end +GD_HardwareInfo_t GD_HardwareInfo; #define printf_rm(...) DEBUG_LOG(GDROM, __VA_ARGS__) #define printf_ata(...) DEBUG_LOG(GDROM, __VA_ARGS__) @@ -240,7 +241,7 @@ void gd_set_state(gd_states state) break; case gds_process_set_mode: - memcpy(&reply_11[set_mode_offset],pio_buff.data ,pio_buff.size<<1); + memcpy((u8 *)&GD_HardwareInfo + set_mode_offset, pio_buff.data, pio_buff.size << 1); //end pio transfer ;) gd_set_state(gds_pio_end); break; @@ -434,6 +435,53 @@ void gd_process_ata_cmd() }; } +u32 gd_get_subcode(u32 format, u32 fad, u8 *subc_info) +{ + subc_info[0] = 0; + subc_info[1] = 0x15; // no audio status info + if (format == 0) + { + subc_info[2] = 0; + subc_info[3] = 100; + libGDR_ReadSubChannel(subc_info + 4, 0, 100 - 4); + } + else + { + u32 elapsed; + u32 tracknum = libGDR_GetTrackNumber(fad, elapsed); + + //2 DATA Length MSB (0 = 0h) + subc_info[2] = 0; + //3 DATA Length LSB (14 = Eh) + subc_info[3] = 0xE; + //4 Control ADR + subc_info[4] = (SecNumber.DiscFormat == 0 ? 0 : 0x40) | 1; // Control = 4 for data track + //5-13 DATA-Q + u8* data_q = &subc_info[5 - 1]; + //-When ADR = 1 + //1 TNO - track number + data_q[1] = tracknum; + //2 X - index within track + data_q[2] = 1; + //3-5 Elapsed FAD within track + data_q[3] = elapsed >> 16; + data_q[4] = elapsed >> 8; + data_q[5] = elapsed; + //6 ZERO + data_q[6] = 0; + //7-9 FAD + data_q[7] = fad >> 16; + data_q[8] = fad >> 8; + data_q[9] = fad; + DEBUG_LOG(GDROM, "gd_get_subcode: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", + subc_info[0], subc_info[1], subc_info[2], subc_info[3], + subc_info[4], subc_info[5], subc_info[6], subc_info[7], + subc_info[8], subc_info[9], subc_info[10], subc_info[11], + subc_info[12], subc_info[13]); + } + return subc_info[3]; +} + void gd_process_spi_cmd() { @@ -461,7 +509,7 @@ void gd_process_spi_cmd() case SPI_REQ_MODE: printf_spicmd("SPI_REQ_MODE"); - gd_spi_pio_end((u8*)&reply_11[packet_cmd.data_8[2]>>1],packet_cmd.data_8[4]); + gd_spi_pio_end((u8*)&GD_HardwareInfo + packet_cmd.data_8[2], packet_cmd.data_8[4]); break; ///////////////////////////////////////////////// @@ -723,79 +771,10 @@ void gd_process_spi_cmd() { printf_spicmd("SPI_GET_SCD"); - u32 format; - format=packet_cmd.data_8[1]&0xF; - u32 sz; + u32 format = packet_cmd.data_8[1] & 0xF; u8 subc_info[100]; - - - //0 Reserved - subc_info[0]=0; - //1 Audio status - if (SecNumber.Status==GD_STANDBY) - { - //13h Audio playback ended normally - subc_info[1]=0x13; - } - else if (SecNumber.Status==GD_PAUSE) - { - //12h Audio playback paused - subc_info[1]=0x12; - } - else if (SecNumber.Status==GD_PLAY) - { - //11h Audio playback in progress - subc_info[1]=0x11; - } - else - { - if (cdda.playing) - subc_info[1]=0x11;//11h Audio playback in progress - else - subc_info[1]=0x15;//15h No audio status information - } - - subc_info[1]=0x15; - - if (format==0) - { - sz=100; - subc_info[2]=0; - subc_info[3]=100; - libGDR_ReadSubChannel(subc_info+4,0,96); - } - else - { - //2 DATA Length MSB (0 = 0h) - subc_info[2]=0; - //3 DATA Length LSB (14 = Eh) - subc_info[3]=0xE; - //4 Control ADR - subc_info[4]=(4<<4) | (1); //Audio :p - //5-13 DATA-Q - u8* data_q=&subc_info[5-1]; - //-When ADR = 1 - //Byte Description - //1 TNO - data_q[1]=1;//Track number .. dunno whats it :P gotta parse toc xD ;p - //2 X - data_q[2]=1;//gap #1 (main track) - //3-5 Elapsed FAD within track - u32 FAD_el=cdda.CurrAddr.FAD-cdda.StartAddr.FAD; - data_q[3]=0;//(u8)(FAD_el>>16); - data_q[4]=0;//(u8)(FAD_el>>8); - data_q[5]=0;//(u8)(FAD_el>>0); - //6 0 0 0 0 0 0 0 0 - data_q[6]=0;// - //7-9 -> seems to be FAD - data_q[7]=0; //(u8)(cdda.CurrAddr.FAD>>16); - data_q[8]=0x0; //(u8)(cdda.CurrAddr.FAD>>8); - data_q[9]=0x96;//(u8)(cdda.CurrAddr.FAD>>0); - sz=0xE; - printf_subcode("NON raw subcode read -- partially wrong [format=%d]",format); - } - - gd_spi_pio_end((u8*)&subc_info[0],sz); + u32 size = gd_get_subcode(format, read_params.start_sector - 1, subc_info); + gd_spi_pio_end(subc_info, size); } break; @@ -1135,4 +1114,15 @@ void gdrom_reg_Reset(bool hard) sb_rio_register(SB_GDEN_addr, RIO_WF, 0, &GDROM_DmaEnable); SB_GDST = 0; SB_GDEN = 0; + // set default hardware information + memset(&GD_HardwareInfo, 0, sizeof(GD_HardwareInfo)); + GD_HardwareInfo.speed = 0x0; + GD_HardwareInfo.standby_hi = 0x00; + GD_HardwareInfo.standby_lo = 0xb4; + GD_HardwareInfo.read_flags = 0x19; + GD_HardwareInfo.read_retry = 0x08; + memcpy(GD_HardwareInfo.drive_info, "SE ", sizeof(GD_HardwareInfo.drive_info)); + memcpy(GD_HardwareInfo.system_version, "Rev 6.43", sizeof(GD_HardwareInfo.system_version)); + memcpy(GD_HardwareInfo.system_date, "990408", sizeof(GD_HardwareInfo.system_date)); + } diff --git a/core/hw/gdrom/gdromv3.h b/core/hw/gdrom/gdromv3.h index 057fe4554..97dfd3c34 100644 --- a/core/hw/gdrom/gdromv3.h +++ b/core/hw/gdrom/gdromv3.h @@ -11,6 +11,8 @@ void gdrom_reg_Reset(bool Manual); u32 ReadMem_gdrom(u32 Addr, u32 sz); void WriteMem_gdrom(u32 Addr, u32 data, u32 sz); +u32 gd_get_subcode(u32 format, u32 fad, u8 *subc_info); + enum gd_states { //Generic @@ -222,6 +224,23 @@ union ByteCount_t u16 full; } ; +// REQ_MODE / SET_MODE +struct GD_HardwareInfo_t +{ + u8 _res0[2]; + u8 speed; + u8 _res1; + u8 standby_hi; + u8 standby_lo; + u8 read_flags; + u8 _res2[2]; + u8 read_retry; + char drive_info[8]; + char system_version[8]; + char system_date[6]; +}; +extern GD_HardwareInfo_t GD_HardwareInfo; + #define GD_BUSY 0x00 // State transition #define GD_PAUSE 0x01 // Pause #define GD_STANDBY 0x02 // Standby (drive stop) diff --git a/core/hw/holly/sb_mem.cpp b/core/hw/holly/sb_mem.cpp index b58c036c5..0ea46a3a0 100644 --- a/core/hw/holly/sb_mem.cpp +++ b/core/hw/holly/sb_mem.cpp @@ -46,11 +46,12 @@ static bool nvmemOptional() bool LoadRomFiles(const string& root) { + bool rom_loaded = false; if (settings.platform.system != DC_PLATFORM_ATOMISWAVE) { if (!sys_rom->Load(root, getRomPrefix(), "%boot.bin;%boot.bin.bin;%bios.bin;%bios.bin.bin", "bootrom")) { - if (settings.platform.system == DC_PLATFORM_DREAMCAST) + if (settings.platform.system == DC_PLATFORM_DREAMCAST && !settings.bios.UseReios) { // Dreamcast absolutely needs a BIOS msgboxf("Unable to find bios in %s. Exiting...", MBX_ICONERROR, root.c_str()); @@ -58,7 +59,14 @@ bool LoadRomFiles(const string& root) } } else + { bios_loaded = true; + rom_loaded = true; + } + } + else + { + rom_loaded = true; } bool rc; if (settings.platform.system == DC_PLATFORM_DREAMCAST) @@ -106,7 +114,7 @@ bool LoadRomFiles(const string& root) if (settings.platform.system == DC_PLATFORM_ATOMISWAVE) sys_rom->Load(get_game_save_prefix() + ".nvmem2"); - return true; + return rom_loaded; } void SaveRomFiles(const string& root) @@ -119,12 +127,9 @@ void SaveRomFiles(const string& root) sys_rom->Save(get_game_save_prefix() + ".nvmem2"); } -bool LoadHle(const string& root) { - if (!sys_nvmem->Load(root, getRomPrefix(), "%nvmem.bin;%flash_wb.bin;%flash.bin;%flash.bin.bin", "nvram")) { - INFO_LOG(FLASHROM, "No nvmem loaded"); - } - - return reios_init(sys_rom->data, sys_nvmem->data); +bool HleInit() +{ + return reios_init(sys_rom->data, sys_nvmem); } u32 ReadFlash(u32 addr,u32 sz) { return sys_nvmem->Read(addr,sz); } diff --git a/core/hw/sh4/sh4_mem.h b/core/hw/sh4/sh4_mem.h index 9fe5886bb..29271dc10 100644 --- a/core/hw/sh4/sh4_mem.h +++ b/core/hw/sh4/sh4_mem.h @@ -100,4 +100,4 @@ u32 GetRamPageFromAddress(u32 RamAddress); bool LoadRomFiles(const string& root); void SaveRomFiles(const string& root); -bool LoadHle(const string& root); +bool HleInit(); diff --git a/core/imgread/ImgReader.cpp b/core/imgread/ImgReader.cpp index 09e6be56d..e0562688d 100644 --- a/core/imgread/ImgReader.cpp +++ b/core/imgread/ImgReader.cpp @@ -26,6 +26,19 @@ void libGDR_GetToc(u32* toc,u32 area) { GetDriveToc(toc,(DiskArea)area); } + +u32 libGDR_GetTrackNumber(u32 sector, u32& elapsed) +{ + for (int i = 0; i < disc->tracks.size(); i++) + if (disc->tracks[i].StartFAD <= sector && (sector <= disc->tracks[i].EndFAD || disc->tracks[i].EndFAD == 0)) + { + elapsed = sector - disc->tracks[i].StartFAD; + return i + 1; + } + elapsed = 0; + return 0xAA; +} + //TODO : fix up u32 libGDR_GetDiscType() { @@ -39,28 +52,7 @@ void libGDR_GetSessionInfo(u8* out,u8 ses) { GetDriveSessionInfo(out,ses); } -/* -void EXPORT_CALL handle_SwitchDisc(u32 id,void* w,void* p) -{ - //msgboxf("This feature is not yet implemented",MB_ICONWARNING); - //return; - TermDrive(); - - NullDriveDiscType=Busy; - DriveNotifyEvent(DiskChange,0); - Sleep(150); //busy for a bit - NullDriveDiscType=Open; - DriveNotifyEvent(DiskChange,0); - Sleep(150); //tray is open - - while(!InitDrive(2))//no "cancel" - msgboxf("Init Drive failed, disc must be valid for swap",0x00000010L); - - DriveNotifyEvent(DiskChange,0); - //new disc is in -} -*/ //It's supposed to reset everything (if not a soft reset) void libGDR_Reset(bool hard) { diff --git a/core/nullDC.cpp b/core/nullDC.cpp index dd34f4a48..706106d00 100755 --- a/core/nullDC.cpp +++ b/core/nullDC.cpp @@ -465,16 +465,14 @@ void dc_start_game(const char *path) { if (settings.platform.system == DC_PLATFORM_DREAMCAST) { -#ifdef USE_REIOS if (settings.bios.UseReios) { - if (!LoadHle(get_readonly_data_path(DATA_PATH))) + if (!HleInit()) throw ReicastException("Failed to initialize HLE BIOS"); NOTICE_LOG(BOOT, "Did not load BIOS, using reios"); } else -#endif { throw ReicastException("Cannot find BIOS files in " + data_path); } @@ -632,7 +630,7 @@ void InitSettings() settings.debug.SerialConsole = false; - settings.bios.UseReios = 0; + settings.bios.UseReios = false; settings.reios.ElfFile = ""; settings.validate.OpenGlChecks = false; @@ -827,6 +825,7 @@ void SaveSettings() if (!safemode_game || !settings.dynarec.safemode) cfgSaveBool("config", "Dynarec.safe-mode", settings.dynarec.safemode); cfgSaveInt("config", "Dynarec.SmcCheckLevel", (int)settings.dynarec.SmcCheckLevel); + cfgSaveBool("config", "bios.UseReios", settings.bios.UseReios); // if (!disable_vmem32_game || !settings.dynarec.disable_vmem32) // cfgSaveBool("config", "Dynarec.DisableVmem32", settings.dynarec.disable_vmem32); diff --git a/core/reios/gdrom_hle.cpp b/core/reios/gdrom_hle.cpp index bee6342cf..f6b60ceef 100644 --- a/core/reios/gdrom_hle.cpp +++ b/core/reios/gdrom_hle.cpp @@ -1,6 +1,7 @@ /* Basic gdrom syscall emulation Adapted from some (very) old pre-nulldc hle code + Bits and pieces from redream (https://github.com/inolen/redream) */ #include @@ -9,11 +10,19 @@ #include "hw/sh4/sh4_mem.h" #include "gdrom_hle.h" +#include "hw/gdrom/gdromv3.h" +#include "reios.h" #define SWAP32(a) ((((a) & 0xff) << 24) | (((a) & 0xff00) << 8) | (((a) >> 8) & 0xff00) | (((a) >> 24) & 0xff)) #define debugf(...) DEBUG_LOG(REIOS, __VA_ARGS__) +// FIXME Serialize +u32 LastCommandId = 0xFFFFFFFF; +u32 NextCommandId = 1; +u32 bios_result[4]; // BIOS result vector +u32 cur_sector; + void GDROM_HLE_ReadSES(u32 addr) { u32 s = ReadMem32(addr + 0); @@ -21,21 +30,26 @@ void GDROM_HLE_ReadSES(u32 addr) u32 ba = ReadMem32(addr + 8); u32 bb = ReadMem32(addr + 12); - INFO_LOG(REIOS, "GDROM_HLE_ReadSES: doing nothing w/ %d, %d, %d, %d", s, b, ba, bb); + WARN_LOG(REIOS, "GDROM_HLE_ReadSES: doing nothing w/ %d, %d, %d, %d", s, b, ba, bb); } void GDROM_HLE_ReadTOC(u32 Addr) { - u32 s = ReadMem32(Addr + 0); - u32 b = ReadMem32(Addr + 4); + u32 area = ReadMem32(Addr + 0); + u32 dest = ReadMem32(Addr + 4); - u32* pDst = (u32*)GetMemPtr(b, 0); + u32* pDst = (u32*)GetMemPtr(dest, 0); - // - debugf("GDROM READ TOC : %X %X", s, b); + debugf("GDROM READ TOC : %X %X", area, dest); + if (area == DoubleDensity && libGDR_GetDiscType() != GdRom) + { + // Only GD-ROM has a high-density area but no error is reported + LastCommandId = 0xFFFFFFFF; + return; + } - libGDR_GetToc(pDst, s); + libGDR_GetToc(pDst, area); - //The syscall swaps to LE it seems + // Swap results to LE for (int i = 0; i < 102; i++) { pDst[i] = SWAP32(pDst[i]); } @@ -46,6 +60,7 @@ void read_sectors_to(u32 addr, u32 sector, u32 count) { if (pDst) { libGDR_ReadSector(pDst, sector, count, 2048); + cur_sector = sector + count - 1; } else { u8 temp[2048]; @@ -61,8 +76,8 @@ void read_sectors_to(u32 addr, u32 sector, u32 count) { sector++; count--; } + cur_sector = sector - 1; } - } void GDROM_HLE_ReadDMA(u32 addr) @@ -72,10 +87,10 @@ void GDROM_HLE_ReadDMA(u32 addr) u32 b = ReadMem32(addr + 0x08); u32 u = ReadMem32(addr + 0x0C); - - - debugf("GDROM:\tPIO READ Sector=%d, Num=%d, Buffer=0x%08X, Unk01=0x%08X\n", s, n, b, u); + debugf("GDROM: DMA READ Sector=%d, Num=%d, Buffer=0x%08X, Unk01=0x%08X", s, n, b, u); read_sectors_to(b, s, n); + bios_result[2] = n * 2048; + bios_result[3] = -n * 2048; } void GDROM_HLE_ReadPIO(u32 addr) @@ -85,22 +100,30 @@ void GDROM_HLE_ReadPIO(u32 addr) u32 b = ReadMem32(addr + 0x08); u32 u = ReadMem32(addr + 0x0C); - debugf("GDROM:\tPIO READ Sector=%d, Num=%d, Buffer=0x%08X, Unk01=0x%08X\n", s, n, b, u); + debugf("GDROM: PIO READ Sector=%d, Num=%d, Buffer=0x%08X, Unk01=0x%08X", s, n, b, u); read_sectors_to(b, s, n); + bios_result[2] = n * 2048; + bios_result[3] = -n * 2048; } void GDCC_HLE_GETSCD(u32 addr) { - u32 s = ReadMem32(addr + 0x00); - u32 n = ReadMem32(addr + 0x04); - u32 b = ReadMem32(addr + 0x08); - u32 u = ReadMem32(addr + 0x0C); + u32 format = ReadMem32(addr + 0x00); + u32 size = ReadMem32(addr + 0x04); + u32 dest = ReadMem32(addr + 0x08); - INFO_LOG(REIOS, "GDROM: Doing nothing for GETSCD [0]=%d, [1]=%d, [2]=0x%08X, [3]=0x%08X", s, n, b, u); + INFO_LOG(REIOS, "GDROM: GETSCD format %x size %x dest %08x", format, size, dest); + + u8 scd[100]; + gd_get_subcode(format, cur_sector, scd); + verify(scd[3] == size); + + memcpy(GetMemPtr(dest, size), scd, size); + + // record size of pio transfer to gdrom + bios_result[2] = size; } -#define r Sh4cntx.r - u32 SecMode[4]; @@ -109,115 +132,277 @@ void GD_HLE_Command(u32 cc, u32 prm) switch(cc) { case GDCC_GETTOC: - INFO_LOG(REIOS, "GDROM:\t*FIXME* CMD GETTOC CC:%X PRM:%X",cc,prm); + WARN_LOG(REIOS, "GDROM: *FIXME* CMD GETTOC CC:%X PRM:%X",cc,prm); break; case GDCC_GETTOC2: - GDROM_HLE_ReadTOC(r[5]); + GDROM_HLE_ReadTOC(prm); break; case GDCC_GETSES: - debugf("GDROM:\tGETSES CC:%X PRM:%X\n", cc, prm); - GDROM_HLE_ReadSES(r[5]); + debugf("GDROM: GETSES CC:%X PRM:%X", cc, prm); + GDROM_HLE_ReadSES(prm); break; case GDCC_INIT: - INFO_LOG(REIOS, "GDROM:\tCMD INIT CC:%X PRM:%X",cc,prm); + INFO_LOG(REIOS, "GDROM: CMD INIT CC:%X PRM:%X",cc,prm); break; case GDCC_PIOREAD: - GDROM_HLE_ReadPIO(r[5]); + GDROM_HLE_ReadPIO(prm); break; case GDCC_DMAREAD: - debugf("GDROM:\tCMD DMAREAD CC:%X PRM:%X", cc, prm); - GDROM_HLE_ReadDMA(r[5]); + debugf("GDROM: CMD DMAREAD CC:%X PRM:%X", cc, prm); + GDROM_HLE_ReadDMA(prm); break; case GDCC_PLAY_SECTOR: - INFO_LOG(REIOS, "GDROM:\tCMD PLAYSEC? CC:%X PRM:%X",cc,prm); + WARN_LOG(REIOS, "GDROM: CMD PLAYSEC? CC:%X PRM:%X",cc,prm); break; case GDCC_RELEASE: - INFO_LOG(REIOS, "GDROM:\tCMD RELEASE? CC:%X PRM:%X",cc,prm); + WARN_LOG(REIOS, "GDROM: CMD RELEASE? CC:%X PRM:%X",cc,prm); break; - case GDCC_STOP: INFO_LOG(REIOS, "GDROM:\tCMD STOP CC:%X PRM:%X",cc,prm); break; - case GDCC_SEEK: INFO_LOG(REIOS, "GDROM:\tCMD SEEK CC:%X PRM:%X",cc,prm); break; - case GDCC_PLAY: INFO_LOG(REIOS, "GDROM:\tCMD PLAY CC:%X PRM:%X",cc,prm); break; - case GDCC_PAUSE:INFO_LOG(REIOS, "GDROM:\tCMD PAUSE CC:%X PRM:%X",cc,prm); break; + case GDCC_STOP: + WARN_LOG(REIOS, "GDROM: CMD STOP CC:%X PRM:%X",cc,prm); + break; + + case GDCC_SEEK: + WARN_LOG(REIOS, "GDROM: CMD SEEK CC:%X PRM:%X",cc,prm); + break; + + case GDCC_PLAY: + WARN_LOG(REIOS, "GDROM: CMD PLAY PRM:%X args: %x %x %x %x", prm, ReadMem32(prm), ReadMem32(prm + 4), ReadMem32(prm + 8), ReadMem32(prm + 12)); + break; + + case GDCC_PAUSE: + WARN_LOG(REIOS, "GDROM: CMD PAUSE CC:%X PRM:%X",cc,prm); + break; case GDCC_READ: - INFO_LOG(REIOS, "GDROM:\tCMD READ CC:%X PRM:%X",cc,prm); + { + u32 s = ReadMem32(prm + 0x00); + u32 n = ReadMem32(prm + 0x04); + u32 b = ReadMem32(prm + 0x08); + u32 u = ReadMem32(prm + 0x0C); + + WARN_LOG(REIOS, "GDROM: CMD READ PRM:%X Sector=%d, Num=%d, Buffer=0x%08X, Unk01=%08x", prm, s, n, b, u); + } break; case GDCC_GETSCD: - debugf("GDROM:\tGETSCD CC:%X PRM:%X\n",cc,prm); - GDCC_HLE_GETSCD(r[5]); + debugf("GDROM: GETSCD CC:%X PRM:%X",cc,prm); + GDCC_HLE_GETSCD(prm); break; - default: INFO_LOG(REIOS, "GDROM:\tUnknown GDROM CC:%X PRM:%X",cc,prm); break; + case GDCC_REQ_MODE: + { + debugf("GDROM: REQ_MODE PRM:%X", prm); + u32 dest = ReadMem32(prm); + u32 *out = (u32 *)GetMemPtr(dest, 16); + out[0] = GD_HardwareInfo.speed; + out[1] = (GD_HardwareInfo.standby_hi << 8) | GD_HardwareInfo.standby_lo; + out[2] = GD_HardwareInfo.read_flags; + out[3] = GD_HardwareInfo.read_retry; + + // record size of pio transfer to gdrom + bios_result[2] = 0xa; + } + break; + + case GDCC_SET_MODE: + { + u32 speed = ReadMem32(prm); + u32 standby = ReadMem32(prm + 4); + u32 read_flags = ReadMem32(prm + 8); + u32 read_retry = ReadMem32(prm + 12); + + debugf("GDROM: SET_MODE PRM:%X speed %x standby %x read_flags %x read_retry %x", prm, speed, standby, read_flags, read_retry); + + GD_HardwareInfo.speed = speed; + GD_HardwareInfo.standby_hi = (standby & 0xff00) >> 8; + GD_HardwareInfo.standby_lo = standby & 0xff; + GD_HardwareInfo.read_flags = read_flags; + GD_HardwareInfo.read_retry = read_retry; + + // record size of pio transfer to gdrom + bios_result[2] = 0xa; + } + break; + + case GDCC_GET_VER: + { + u32 dest = ReadMem32(prm); + + debugf("GDROM: GDCC_GET_VER dest %x", dest); + + char ver[] = "GDC Version 1.10 1999-03-31 "; + u32 len = (u32)strlen(ver); + + // 0x8c0013b8 (offset 0xd0 in the gdrom state struct) is then loaded and + // overwrites the last byte. no idea what this is, but seems to be hard + // coded to 0x02 on boot + ver[len - 1] = 0x02; + + memcpy(GetMemPtr(dest, len), ver, len); + } + break; + + case GDCC_REQ_STAT: + { + // odd, but this function seems to get passed 4 unique pointers + u32 dst0 = ReadMem32(prm); + u32 dst1 = ReadMem32(prm + 4); + u32 dst2 = ReadMem32(prm + 8); + u32 dst3 = ReadMem32(prm + 12); + + debugf("GDROM: GDCC_REQ_STAT dst0=%08x dst1=%08x dst2=%08x dst3=%08x", dst0, dst1, dst2, dst3); + + // bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 + // byte | | | | | | | | + // ------------------------------------------------------ + // 0 | 0 | 0 | 0 | 0 | status + // ------------------------------------------------------ + // 1 | 0 | 0 | 0 | 0 | repeat count + // ------------------------------------------------------ + // 2-3 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 + WriteMem32(dst0, 2); // repeat 0, status 2 (standby) + + // bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 + // byte | | | | | | | | + // ------------------------------------------------------ + // 0 | subcode q track number + // ------------------------------------------------------ + // 1-3 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 + u32 elapsed; + u32 tracknum = libGDR_GetTrackNumber(cur_sector, elapsed); + WriteMem32(dst1, tracknum); + + // bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 + // byte | | | | | | | | + // ------------------------------------------------------ + // 0-2 | fad (little-endian) + // ------------------------------------------------------ + // 3 | address | control + // FIXME address/control + u32 out = ((0x4) << 28) | ((0x1) << 24) | (cur_sector & 0x00ffffff); + WriteMem32(dst2, out); + + // bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 + // byte | | | | | | | | + // ------------------------------------------------------ + // 0 | subcode q index number + // ------------------------------------------------------ + // 1-3 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 + WriteMem32(dst3, 1); + + // record pio transfer size + bios_result[2] = 0xa; + } + break; + default: + WARN_LOG(REIOS, "GDROM: Unknown GDROM CC:%X PRM:%X", cc, prm); + break; } } +#define r Sh4cntx.r + void gdrom_hle_op() { - static u32 last_cmd = 0xFFFFFFFF; // only works for last cmd, might help somewhere - static u32 dwReqID=0xF0FFFFFF; // ReqID, starting w/ high val - if( SYSCALL_GDROM == r[6] ) // GDROM SYSCALL { switch(r[7]) // COMMAND CODE { - // *FIXME* NEED RET case GDROM_SEND_COMMAND: // SEND GDROM COMMAND RET: - if failed + req id - debugf("\nGDROM:\tHLE SEND COMMAND CC:%X param ptr: %X\n",r[4],r[5]); - GD_HLE_Command(r[4],r[5]); - last_cmd = r[0] = --dwReqID; // RET Request ID - break; - - case GDROM_CHECK_COMMAND: // - r[0] = last_cmd == r[4] ? 2 : 0; // RET Finished : Invalid - debugf("\nGDROM:\tHLE CHECK COMMAND REQID:%X param ptr: %X -> %X\n", r[4], r[5], r[0]); - last_cmd = 0xFFFFFFFF; // INVALIDATE CHECK CMD - break; - - // NO return, NO params - case GDROM_MAIN: - debugf("\nGDROM:\tHLE GDROM_MAIN\n"); + debugf("GDROM: HLE SEND COMMAND CC:%X param ptr: %X", r[4], r[5]); + memset(bios_result, 0, sizeof(bios_result)); + LastCommandId = r[0] = NextCommandId++; // Request Id + GD_HLE_Command(r[4], r[5]); break; - case GDROM_INIT: INFO_LOG(REIOS, "GDROM:\tHLE GDROM_INIT"); break; - case GDROM_RESET: INFO_LOG(REIOS, "GDROM:\tHLE GDROM_RESET"); break; + case GDROM_CHECK_COMMAND: + if (r[4] != LastCommandId) + { + r[0] = -1; // Error (examine extended status information for cause of failure) + bios_result[0] = 5; // Invalid command id + bios_result[1] = 0; + bios_result[2] = 0; + bios_result[3] = 0; + } + else + { + r[0] = 2; // Finished + } + debugf("GDROM: HLE CHECK COMMAND REQID:%X param ptr: %X -> %X", r[4], r[5], r[0]); + LastCommandId = 0xFFFFFFFF; // INVALIDATE CHECK CMD + WriteMem32(r[5], bios_result[0]); + WriteMem32(r[5] + 4, bios_result[1]); + WriteMem32(r[5] + 8, bios_result[2]); + WriteMem32(r[5] + 12, bios_result[3]); + break; - case GDROM_CHECK_DRIVE: // - debugf("\nGDROM:\tHLE GDROM_CHECK_DRIVE r4:%X\n",r[4]); - WriteMem32(r[4]+0,0x02); // STANDBY - WriteMem32(r[4]+4,libGDR_GetDiscType()); // CDROM | 0x80 for GDROM - r[0]=0; // RET SUCCESS - break; + case GDROM_MAIN: + //debugf("GDROM: HLE GDROM_MAIN"); + break; - case GDROM_ABORT_COMMAND: // - INFO_LOG(REIOS, "GDROM:\tHLE GDROM_ABORT_COMMAND r4:%X",r[4]); - r[0]=-1; // RET FAILURE - break; + case GDROM_INIT: + INFO_LOG(REIOS, "GDROM: HLE GDROM_INIT"); + LastCommandId = 0xFFFFFFFF; + break; + + case GDROM_RESET: + INFO_LOG(REIOS, "GDROM: HLE GDROM_RESET"); + break; + + case GDROM_CHECK_DRIVE: + //debugf("GDROM: HLE GDROM_CHECK_DRIVE r4:%X", r[4]); + WriteMem32(r[4] + 0, 0x02); // STANDBY + if (strstr(reios_device_info, "GD-ROM") != NULL) + WriteMem32(r[4] + 4, GdRom); + else + WriteMem32(r[4] + 4, libGDR_GetDiscType()); + r[0] = 0; // Success + break; + + case GDROM_ABORT_COMMAND: + INFO_LOG(REIOS, "GDROM: HLE GDROM_ABORT_COMMAND r4:%X",r[4]); + r[0] = -1; // Failure + break; - case GDROM_SECTOR_MODE: // - INFO_LOG(REIOS, "GDROM:\tHLE GDROM_SECTOR_MODE PTR_r4:%X",r[4]); + case GDROM_SECTOR_MODE: + INFO_LOG(REIOS, "GDROM: HLE GDROM_SECTOR_MODE PTR_r4:%X",r[4]); for(int i=0; i<4; i++) { SecMode[i] = ReadMem32(r[4]+(i<<2)); INFO_LOG(REIOS, "%08X", SecMode[i]); } - r[0]=0; // RET SUCCESS - break; + r[0] = 0; // Success + break; - default: INFO_LOG(REIOS, "GDROM:\tUnknown SYSCALL: %X",r[7]); break; + default: + WARN_LOG(REIOS, "GDROM: Unknown SYSCALL: %X",r[7]); + break; } } else // MISC { - INFO_LOG(REIOS, "SYSCALL:\tSYSCALL: %X", r[7]); + switch(r[7]) + { + case MISC_INIT: + WARN_LOG(REIOS, "GDROM: MISC_INIT not implemented"); + break; + + case MISC_SETVECTOR: + WARN_LOG(REIOS, "GDROM: MISC_SETVECTOR not implemented"); + break; + + default: + WARN_LOG(REIOS, "GDROM: Unknown MISC command %x", r[7]); + break; + } } } diff --git a/core/reios/gdrom_hle.h b/core/reios/gdrom_hle.h index 06b30a919..c6e533ec9 100644 --- a/core/reios/gdrom_hle.h +++ b/core/reios/gdrom_hle.h @@ -1,32 +1,38 @@ #pragma once -#define SYSCALL_GDROM (0x00) +#define SYSCALL_GDROM 0x00 -#define GDROM_SEND_COMMAND (0x00) -#define GDROM_CHECK_COMMAND (0x01) -#define GDROM_MAIN (0x02) -#define GDROM_INIT (0x03) -#define GDROM_CHECK_DRIVE (0x04) -#define GDROM_ABORT_COMMAND (0x08) -#define GDROM_RESET (0x09) -#define GDROM_SECTOR_MODE (0x0A) +#define GDROM_SEND_COMMAND 0x00 +#define GDROM_CHECK_COMMAND 0x01 +#define GDROM_MAIN 0x02 +#define GDROM_INIT 0x03 +#define GDROM_CHECK_DRIVE 0x04 +#define GDROM_ABORT_COMMAND 0x08 +#define GDROM_RESET 0x09 +#define GDROM_SECTOR_MODE 0x0A -#define GDCC_PIOREAD (16) -#define GDCC_DMAREAD (17) -#define GDCC_GETTOC (18) -#define GDCC_GETTOC2 (19) -#define GDCC_PLAY (20) -#define GDCC_PLAY_SECTOR (21) -#define GDCC_PAUSE (22) -#define GDCC_RELEASE (23) -#define GDCC_INIT (24) -#define GDCC_SEEK (27) -#define GDCC_READ (28) -#define GDCC_STOP (33) -#define GDCC_GETSCD (34) -#define GDCC_GETSES (35) +#define GDCC_PIOREAD 0x10 +#define GDCC_DMAREAD 0x11 +#define GDCC_GETTOC 0x12 +#define GDCC_GETTOC2 0x13 +#define GDCC_PLAY 0x14 +#define GDCC_PLAY_SECTOR 0x15 +#define GDCC_PAUSE 0x16 +#define GDCC_RELEASE 0x17 +#define GDCC_INIT 0x18 +#define GDCC_SEEK 0x1b +#define GDCC_READ 0x1c +#define GDCC_REQ_MODE 0x1e +#define GDCC_SET_MODE 0x1f +#define GDCC_STOP 0x21 +#define GDCC_GETSCD 0x22 +#define GDCC_GETSES 0x23 +#define GDCC_REQ_STAT 0x24 +#define GDCC_GET_VER 0x28 +#define MISC_INIT 0x00 +#define MISC_SETVECTOR 0x01 #define CTOC_LBA(n) (n) #define CTOC_ADR(n) (n<<24) @@ -34,4 +40,4 @@ #define CTOC_TRACK(n) (n<<16) void gdrom_hle_op(); -void GD_HLE_Command(u32 cc, u32 prm); \ No newline at end of file +void GD_HLE_Command(u32 cc, u32 prm); diff --git a/core/reios/iso9660.h b/core/reios/iso9660.h new file mode 100644 index 000000000..393ff0832 --- /dev/null +++ b/core/reios/iso9660.h @@ -0,0 +1,557 @@ +/* + Copyright (C) 2003-2008, 2012-2013 + Rocky Bernstein + Copyright (C) 2000 Herbert Valerio Riedel + + See also iso9660.h by Eric Youngdale (1993). + + Copyright 1993 Yggdrasil Computing, Incorporated + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef CDIO_ISO9660_H_ +#define CDIO_ISO9660_H_ + +#include + +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4) +#define GNUC_PACKED \ + __attribute__((packed)) +#else /* !__GNUC__ */ +#define GNUC_PACKED +#endif /* !__GNUC__ */ + +#if defined(__MINGW32__) +# define PRAGMA_BEGIN_PACKED _Pragma("pack(push)") \ + _Pragma("pack(1)") +# define PRAGMA_END_PACKED _Pragma("pack(pop)") +#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901) + /* should work with most EDG-frontend based compilers */ +# define PRAGMA_BEGIN_PACKED _Pragma("pack(1)") +# define PRAGMA_END_PACKED _Pragma("pack()") +#elif defined(_MSC_VER) +# define PRAGMA_BEGIN_PACKED __pragma(pack(push, 1)) +# define PRAGMA_END_PACKED __pragma(pack(pop)) +#else /* neither gcc nor _Pragma() available... */ + /* ...so let's be naive and hope the regression testsuite is run... */ +# define PRAGMA_BEGIN_PACKED +# define PRAGMA_END_PACKED +#endif + + +/** \brief ISO 9660 Integer and Character types + +These are described in the section 7 of the ISO 9660 (or ECMA 119) +specification. +*/ + +typedef uint8_t iso711_t; /*! See section 7.1.1 */ +typedef int8_t iso712_t; /*! See section 7.1.2 */ +typedef uint16_t iso721_t; /*! See section 7.2.1 */ +typedef uint16_t iso722_t; /*! See section 7.2.2 */ +typedef uint32_t iso723_t; /*! See section 7.2.3 */ +typedef uint32_t iso731_t; /*! See section 7.3.1 */ +typedef uint32_t iso732_t; /*! See section 7.3.2 */ +typedef uint64_t iso733_t; /*! See section 7.3.3 */ + +typedef char achar_t; /*! See section 7.4.1 */ +typedef char dchar_t; /*! See section 7.4.1 */ + +#ifndef EMPTY_ARRAY_SIZE +#define EMPTY_ARRAY_SIZE 0 +#endif + +#ifdef ISODCL +#undef ISODCL +#endif +/* This part borrowed from the bsd386 isofs */ +#define ISODCL(from, to) ((to) - (from) + 1) + +#define MIN_TRACK_SIZE 4*75 +#define MIN_ISO_SIZE MIN_TRACK_SIZE + +/*! The below isn't really an enumeration one would really use in a + program; things are done this way so that in a debugger one can to + refer to the enumeration value names such as in a debugger + expression and get something. With the more common a \#define + mechanism, the name/value assocation is lost at run time. + */ +extern enum iso_enum1_s { + ISO_PVD_SECTOR = 16, /**< Sector of Primary Volume Descriptor. */ + ISO_EVD_SECTOR = 17, /**< Sector of End Volume Descriptor. */ + LEN_ISONAME = 31, /**< Size in bytes of the filename + portion + null byte. */ + ISO_MAX_SYSTEM_ID = 32, /**< Maximum number of characters in a system + id. */ + MAX_ISONAME = 37, /**< Size in bytes of the filename + portion + null byte. */ + ISO_MAX_PREPARER_ID = 128, /**< Maximum number of characters in a + preparer id. */ + MAX_ISOPATHNAME = 255, /**< Maximum number of characters in the + entire ISO 9660 filename. */ + ISO_BLOCKSIZE = 2048 /**< Number of bytes in an ISO 9660 block. */ + +} iso_enums1; + +/*! An enumeration for some of the ISO_* \#defines below. This isn't + really an enumeration one would really use in a program it is here + to be helpful in debuggers where wants just to refer to the + ISO_*_ names and get something. + */ + +/*! ISO 9660 directory flags. */ +extern enum iso_flag_enum_s { + ISO_FILE = 0, /**< Not really a flag... */ + ISO_EXISTENCE = 1, /**< Do not make existence known (hidden) */ + ISO_DIRECTORY = 2, /**< This file is a directory */ + ISO_ASSOCIATED = 4, /**< This file is an associated file */ + ISO_RECORD = 8, /**< Record format in extended attr. != 0 */ + ISO_PROTECTION = 16, /**< No read/execute perm. in ext. attr. */ + ISO_DRESERVED1 = 32, /**<, Reserved bit 5 */ + ISO_DRESERVED2 = 64, /**<, Reserved bit 6 */ + ISO_MULTIEXTENT = 128, /**< Not final entry of a mult. ext. file */ +} iso_flag_enums; + +/*! Volume descriptor types */ +extern enum iso_vd_enum_s { + ISO_VD_BOOT_RECORD = 0, /**< CD is bootable */ + ISO_VD_PRIMARY = 1, /**< Is in any ISO-9660 */ + ISO_VD_SUPPLEMENTARY = 2, /**< Used by Joliet, for example */ + ISO_VD_PARITION = 3, /**< Indicates a partition of a CD */ + ISO_VD_END = 255 +} iso_vd_enums; + + +/*! + An ISO filename is: + abcd.eee -> + filename.ext;version# + + For ISO-9660 Level 1, the maximum needed string length is: + +@code + 30 chars (filename + ext) + + 2 chars ('.' + ';') + + 5 chars (strlen("32767")) + + 1 null byte + ================================ + = 38 chars +@endcode + +*/ + +/*! \brief Maximum number of characters in a publisher id. */ +#define ISO_MAX_PUBLISHER_ID 128 + +/*! \brief Maximum number of characters in an application id. */ +#define ISO_MAX_APPLICATION_ID 128 + +/*! \brief Maximum number of characters in a volume id. */ +#define ISO_MAX_VOLUME_ID 32 + +/*! \brief Maximum number of characters in a volume-set id. */ +#define ISO_MAX_VOLUMESET_ID 128 + +/*! String inside frame which identifies an ISO 9660 filesystem. This + string is the "id" field of an iso9660_pvd_t or an iso9660_svd_t. +*/ +extern const char ISO_STANDARD_ID[sizeof("CD001")-1]; + +#define ISO_STANDARD_ID "CD001" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +typedef enum strncpy_pad_check { + ISO9660_NOCHECK = 0, + ISO9660_7BIT, + ISO9660_ACHARS, + ISO9660_DCHARS +} strncpy_pad_check_t; + +PRAGMA_BEGIN_PACKED + +/*! + \brief ISO-9660 shorter-format time structure. See ECMA 9.1.5. + + @see iso9660_dtime + */ +struct iso9660_dtime_s { + iso711_t dt_year; /**< Number of years since 1900 */ + iso711_t dt_month; /**< Has value in range 1..12. Note starts + at 1, not 0 like a tm struct. */ + iso711_t dt_day; /**< Day of the month from 1 to 31 */ + iso711_t dt_hour; /**< Hour of the day from 0 to 23 */ + iso711_t dt_minute; /**< Minute of the hour from 0 to 59 */ + iso711_t dt_second; /**< Second of the minute from 0 to 59 */ + iso712_t dt_gmtoff; /**< GMT values -48 .. + 52 in 15 minute + intervals */ +} GNUC_PACKED; + +typedef struct iso9660_dtime_s iso9660_dtime_t; + +/*! + \brief ISO-9660 longer-format time structure. + + Section 8.4.26.1 of ECMA 119. All values are encoded as character + arrays, eg. '1', '9', '5', '5' for the year 1955 (no null terminated + byte). + + @see iso9660_ltime + */ +struct iso9660_ltime_s { + char lt_year [ISODCL( 1, 4)]; /**< Add 1900 to value + for the Julian + year */ + char lt_month [ISODCL( 5, 6)]; /**< Has value in range + 1..12. Note starts + at 1, not 0 like a + tm struct. */ + char lt_day [ISODCL( 7, 8)]; /**< Day of month: 1..31 */ + char lt_hour [ISODCL( 9, 10)]; /**< hour: 0..23 */ + char lt_minute [ISODCL( 11, 12)]; /**< minute: 0..59 */ + char lt_second [ISODCL( 13, 14)]; /**< second: 0..59 */ + char lt_hsecond [ISODCL( 15, 16)]; /**< The value is in + units of 1/100's of + a second */ + iso712_t lt_gmtoff; /**< Offset from Greenwich Mean Time in number + of 15 min intervals from -48 (West) to +52 + (East) recorded according to 7.1.2 numerical + value */ +} GNUC_PACKED; + +typedef struct iso9660_ltime_s iso9660_ltime_t; +typedef struct iso9660_dir_s iso9660_dir_t; +typedef struct iso9660_stat_s iso9660_stat_t; + +/*! \brief Format of an ISO-9660 directory record + + Section 9.1 of ECMA 119. + + This structure may have an odd length depending on how many + characters there are in the filename! Some compilers (e.g. on + Sun3/mc68020) pad the structures to an even length. For this reason, + we cannot use sizeof (struct iso_path_table) or sizeof (struct + iso_directory_record) to compute on disk sizes. Instead, we use + offsetof(..., name) and add the name size. See mkisofs.h of the + cdrtools package. + + @see iso9660_stat +*/ +struct iso9660_dir_s { + iso711_t length; /*! Length of Directory record (9.1.1) */ + iso711_t xa_length; /*! XA length if XA is used. Otherwise + zero. (9.1.2) */ + iso733_t extent; /*! LBA of first local block allocated + to the extent */ + iso733_t size; /*! data length of File Section. This + does not include the length of + any XA Records. (9.1.2) */ + iso9660_dtime_t recording_time; /*! Recording date and time (9.1.3) */ + uint8_t file_flags; /*! If no XA then zero. If a directory, + then bits 2,3 and 7 are zero. + (9.1.6) */ + iso711_t file_unit_size; /*! File Unit size for the File + Section if the File Section + is recorded in interleaved + mode. Otherwise zero. (9.1.7) */ + iso711_t interleave_gap; /*! Interleave Gap size for the + File Section if the File + Section is interleaved. Otherwise + zero. (9.1.8) */ + iso723_t volume_sequence_number; /*! Ordinal number of the volume + in the Volume Set on which + the Extent described by this + Directory Record is + recorded. (9.1.9) */ +/*! MSVC compilers cannot handle a zero sized array in the middle + of a struct, and iso9660_dir_s is reused within iso9660_pvd_s. + Therefore, instead of defining: + iso711_t filename_len; + char filename[]; + we leverage the fact that iso711_t and char are the same size + and use an union. The only gotcha is that the actual string + payload of filename.str[] starts at 1, not 0. */ + union { + iso711_t len; + char str[1]; + } filename; +} GNUC_PACKED; + +/*! + \brief ISO-9660 Primary Volume Descriptor. + */ +struct iso9660_pvd_s { + iso711_t type; /**< ISO_VD_PRIMARY - 1 */ + char id[5]; /**< ISO_STANDARD_ID "CD001" + */ + iso711_t version; /**< value 1 for ECMA 119 */ + char unused1[1]; /**< unused - value 0 */ + achar_t system_id[ISO_MAX_SYSTEM_ID]; /**< each char is an achar */ + dchar_t volume_id[ISO_MAX_VOLUME_ID]; /**< each char is a dchar */ + uint8_t unused2[8]; /**< unused - value 0 */ + iso733_t volume_space_size; /**< total number of + sectors */ + uint8_t unused3[32]; /**< unused - value 0 */ + iso723_t volume_set_size; /**< often 1 */ + iso723_t volume_sequence_number; /**< often 1 */ + iso723_t logical_block_size; /**< sector size, e.g. 2048 */ + iso733_t path_table_size; /**< bytes in path table */ + iso731_t type_l_path_table; /**< first sector of L Path + Table */ + iso731_t opt_type_l_path_table; /**< first sector of optional + L Path Table */ + iso732_t type_m_path_table; /**< first sector of M Path + table */ + iso732_t opt_type_m_path_table; /**< first sector of optional + M Path table */ + iso9660_dir_t root_directory_record; /**< See 8.4.18 and + section 9.1 of + ISO 9660 spec. */ + char root_directory_filename; /**< Is '\\0' or root + directory. Also pads previous + field to 34 bytes */ + dchar_t volume_set_id[ISO_MAX_VOLUMESET_ID]; /**< Volume Set of + which the volume is + a member. See + section 8.4.19 */ + achar_t publisher_id[ISO_MAX_PUBLISHER_ID]; /**< Publisher of + volume. If the first + character is '_' 0x5F, + the remaining bytes + specify a file + containing the user. + If all bytes are " " + (0x20) no publisher + is specified. See + section 8.4.20 of + ECMA 119 */ + achar_t preparer_id[ISO_MAX_PREPARER_ID]; /**< preparer of + volume. If the first + character is '_' 0x5F, + the remaining bytes + specify a file + containing the user. + If all bytes are " " + (0x20) no preparer + is specified. + See section 8.4.21 + of ECMA 119 */ + achar_t application_id[ISO_MAX_APPLICATION_ID]; /**< application + use to create the + volume. If the first + character is '_' 0x5F, + the remaining bytes + specify a file + containing the user. + If all bytes are " " + (0x20) no application + is specified. + See section of 8.4.22 + of ECMA 119 */ + dchar_t copyright_file_id[37]; /**< Name of file for + copyright info. If + all bytes are " " + (0x20), then no file + is identified. See + section 8.4.23 of ECMA 119 + 9660 spec. */ + dchar_t abstract_file_id[37]; /**< See section 8.4.24 of + ECMA 119. */ + dchar_t bibliographic_file_id[37]; /**< See section 7.5 of + ISO 9660 spec. */ + iso9660_ltime_t creation_date; /**< date and time of volume + creation. See section 8.4.26.1 + of the ISO 9660 spec. */ + iso9660_ltime_t modification_date; /**< date and time of the most + recent modification. + See section 8.4.27 of the + ISO 9660 spec. */ + iso9660_ltime_t expiration_date; /**< date and time when volume + expires. See section 8.4.28 + of the ISO 9660 spec. */ + iso9660_ltime_t effective_date; /**< date and time when volume + is effective. See section + 8.4.29 of the ISO 9660 + spec. */ + iso711_t file_structure_version; /**< value 1 for ECMA 119 */ + uint8_t unused4[1]; /**< unused - value 0 */ + char application_data[512]; /**< Application can put + whatever it wants here. */ + uint8_t unused5[653]; /**< Unused - value 0 */ +} GNUC_PACKED; + +typedef struct iso9660_pvd_s iso9660_pvd_t; + +/*! + \brief ISO-9660 Supplementary Volume Descriptor. + + This is used for Joliet Extentions and is almost the same as the + the primary descriptor but two unused fields, "unused1" and "unused3 + become "flags and "escape_sequences" respectively. +*/ +struct iso9660_svd_s { + iso711_t type; /**< ISO_VD_SUPPLEMENTARY - 2 + */ + char id[5]; /**< ISO_STANDARD_ID "CD001" + */ + iso711_t version; /**< value 1 */ + char flags; /**< Section 8.5.3 */ + achar_t system_id[ISO_MAX_SYSTEM_ID]; /**< Section 8.5.4; each char + is an achar */ + dchar_t volume_id[ISO_MAX_VOLUME_ID]; /**< Section 8.5.5; each char + is a dchar */ + char unused2[8]; + iso733_t volume_space_size; /**< total number of + sectors */ + char escape_sequences[32]; /**< Section 8.5.6 */ + iso723_t volume_set_size; /**< often 1 */ + iso723_t volume_sequence_number; /**< often 1 */ + iso723_t logical_block_size; /**< sector size, e.g. 2048 */ + iso733_t path_table_size; /**< 8.5.7; bytes in path + table */ + iso731_t type_l_path_table; /**< 8.5.8; first sector of + little-endian path table */ + iso731_t opt_type_l_path_table; /**< 8.5.9; first sector of + optional little-endian + path table */ + iso732_t type_m_path_table; /**< 8.5.10; first sector of + big-endian path table */ + iso732_t opt_type_m_path_table; /**< 8.5.11; first sector of + optional big-endian path + table */ + iso9660_dir_t root_directory_record; /**< See section 8.5.12 and + 9.1 of ISO 9660 spec. */ + char root_directory_filename; /**< Is '\\0' or root + directory. Also pads previous + field to 34 bytes */ + dchar_t volume_set_id[ISO_MAX_VOLUMESET_ID]; /**< 8.5.13; + dchars */ + achar_t publisher_id[ISO_MAX_PUBLISHER_ID]; /**< + Publisher of volume. + If the first char- + aracter is '_' 0x5F, + the remaining bytes + specify a file + containing the user. + If all bytes are " " + (0x20) no publisher + is specified. See + section 8.5.14 of + ECMA 119 */ + achar_t preparer_id[ISO_MAX_PREPARER_ID]; /**< + Data preparer of + volume. If the first + character is '_' 0x5F, + the remaining bytes + specify a file + containing the user. + If all bytes are " " + (0x20) no preparer + is specified. + See section 8.5.15 + of ECMA 119 */ + achar_t application_id[ISO_MAX_APPLICATION_ID]; /**< application + use to create the + volume. If the first + character is '_' 0x5F, + the remaining bytes + specify a file + containing the user. + If all bytes are " " + (0x20) no application + is specified. + See section of 8.5.16 + of ECMA 119 */ + dchar_t copyright_file_id[37]; /**< Name of file for + copyright info. If + all bytes are " " + (0x20), then no file + is identified. See + section 8.5.17 of ECMA 119 + 9660 spec. */ + dchar_t abstract_file_id[37]; /**< See section 8.5.18 of + ECMA 119. */ + dchar_t bibliographic_file_id[37]; /**< See section 8.5.19 of + ECMA 119. */ + iso9660_ltime_t creation_date; /**< date and time of volume + creation. See section 8.4.26.1 + of the ECMA 119 spec. */ + iso9660_ltime_t modification_date; /**< date and time of the most + recent modification. + See section 8.4.27 of the + ECMA 119 spec. */ + iso9660_ltime_t expiration_date; /**< date and time when volume + expires. See section 8.4.28 + of the ECMA 119 spec. */ + iso9660_ltime_t effective_date; /**< date and time when volume + is effective. See section + 8.4.29 of the ECMA 119 + spec. */ + iso711_t file_structure_version; /**< value 1 for ECMA 119 */ + uint8_t unused4[1]; /**< unused - value 0 */ + char application_data[512]; /**< 8.5.20 Application can put + whatever it wants here. */ + uint8_t unused5[653]; /**< Unused - value 0 */ +} GNUC_PACKED; + +typedef struct iso9660_svd_s iso9660_svd_t; + +PRAGMA_END_PACKED + +/** A mask used in iso9660_ifs_read_vd which allows what kinds + of extensions we allow, eg. Joliet, Rock Ridge, etc. */ +typedef uint8_t iso_extension_mask_t; + +/*! An enumeration for some of the ISO_EXTENSION_* \#defines below. This isn't + really an enumeration one would really use in a program it is here + to be helpful in debuggers where wants just to refer to the + ISO_EXTENSION_*_ names and get something. + */ +extern enum iso_extension_enum_s { + ISO_EXTENSION_JOLIET_LEVEL1 = 0x01, + ISO_EXTENSION_JOLIET_LEVEL2 = 0x02, + ISO_EXTENSION_JOLIET_LEVEL3 = 0x04, + ISO_EXTENSION_ROCK_RIDGE = 0x08, + ISO_EXTENSION_HIGH_SIERRA = 0x10 +} iso_extension_enums; + + +#define ISO_EXTENSION_ALL 0xFF +#define ISO_EXTENSION_NONE 0x00 +#define ISO_EXTENSION_JOLIET \ + (ISO_EXTENSION_JOLIET_LEVEL1 | \ + ISO_EXTENSION_JOLIET_LEVEL2 | \ + ISO_EXTENSION_JOLIET_LEVEL3 ) + + +/** This is an opaque structure. */ +typedef struct _iso9660_s iso9660_t; + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#undef ISODCL +#endif /* CDIO_ISO9660_H_ */ + +/* + * Local variables: + * c-file-style: "gnu" + * tab-width: 8 + * indent-tabs-mode: nil + * End: + */ diff --git a/core/reios/reios.cpp b/core/reios/reios.cpp index 822a331ef..867594dba 100644 --- a/core/reios/reios.cpp +++ b/core/reios/reios.cpp @@ -5,6 +5,7 @@ http://www.ludd.luth.se/~jlo/dc/bootROM.c http://www.ludd.luth.se/~jlo/dc/bootROM.h http://www.ludd.luth.se/~jlo/dc/security_stuff.c + Bits and pieces from redream (https://github.com/inolen/redream) */ #include "reios.h" @@ -15,8 +16,9 @@ #include "descrambl.h" #include "hw/sh4/sh4_mem.h" - +#include "hw/holly/sb_mem.h" #include "hw/naomi/naomi_cart.h" +#include "iso9660.h" #include @@ -33,47 +35,69 @@ #define SYSINFO_ID_ADDR 0x8C001010 -u8* biosrom; -u8* flashrom; -u32 base_fad = 45150; -bool descrambl = false; +static u8* biosrom; +static MemChip *flashrom; +static u32 base_fad = 45150; +static bool descrambl = false; -//Read 32 bit 'bi-endian' integer -//Uses big-endian bytes, that's what the dc bios does too -u32 read_u32bi(u8* ptr) { - return (ptr[4]<<24) | (ptr[5]<<16) | (ptr[6]<<8) | (ptr[7]<<0); +static void reios_pre_init() +{ + if (libGDR_GetDiscType() == GdRom) { + base_fad = 45150; + descrambl = false; + } else { + u8 ses[6]; + libGDR_GetSessionInfo(ses, 0); + libGDR_GetSessionInfo(ses, ses[2]); + base_fad = (ses[3] << 16) | (ses[4] << 8) | (ses[5] << 0); + descrambl = true; + } } -static bool bootfile_inited = false; +static bool reios_locate_bootfile(const char* bootfile="1ST_READ.BIN") +{ + reios_pre_init(); + + // Load IP.BIN bootstrap + libGDR_ReadSector(GetMemPtr(0x8c008000, 0), base_fad, 16, 2048); -bool reios_locate_bootfile(const char* bootfile="1ST_READ.BIN") { u32 data_len = 2048 * 1024; u8* temp = new u8[data_len]; libGDR_ReadSector(temp, base_fad + 16, 1, 2048); + iso9660_pvd_t *pvd = (iso9660_pvd_t *)temp; - if (memcmp(temp, "\001CD001\001", 7) == 0) { - INFO_LOG(REIOS, "reios: iso9660 PVD found"); - u32 lba = read_u32bi(&temp[156 + 2]); //make sure to use big endian - u32 len = read_u32bi(&temp[156 + 10]); //make sure to use big endian + if (pvd->type == 1 && !memcmp(pvd->id, ISO_STANDARD_ID, strlen(ISO_STANDARD_ID)) && pvd->version == 1) + { + INFO_LOG(REIOS, "iso9660 PVD found"); + u32 lba = pvd->root_directory_record.extent & 0xffffffff; + u32 len = pvd->root_directory_record.size & 0xffffffff; - data_len = ((len + 2047) / 2048) *2048; + data_len = ((len + 2047) / 2048) * 2048; - INFO_LOG(REIOS, "reios: iso9660 root_directory, FAD: %d, len: %d", 150 + lba, data_len); - libGDR_ReadSector(temp, 150 + lba, data_len/2048, 2048); + INFO_LOG(REIOS, "iso9660 root_directory, FAD: %d, len: %d", 150 + lba, data_len); + libGDR_ReadSector(temp, 150 + lba, data_len / 2048, 2048); } else { libGDR_ReadSector(temp, base_fad + 16, data_len / 2048, 2048); } - for (int i = 0; i < (data_len-20); i++) { - if (memcmp(temp+i, bootfile, strlen(bootfile)) == 0){ - INFO_LOG(REIOS, "Found %s at %06X", bootfile, i); + int bootfile_len = strlen(bootfile); + while (bootfile_len > 0 && isspace(bootfile[bootfile_len - 1])) + bootfile_len--; + for (int i = 0; i < data_len; ) + { + iso9660_dir_t *dir = (iso9660_dir_t *)&temp[i]; + if (dir->length == 0) + break; - u32 lba = read_u32bi(&temp[i - 33 + 2]); //make sure to use big endian - u32 len = read_u32bi(&temp[i - 33 + 10]); //make sure to use big endian + if ((dir->file_flags & ISO_DIRECTORY) == 0 && memcmp(dir->filename.str + 1, bootfile, bootfile_len) == 0) + { + INFO_LOG(REIOS, "Found %.*s at offset %X", bootfile_len, bootfile, i); + + u32 lba = dir->extent & 0xffffffff; + u32 len = dir->size & 0xffffffff; - INFO_LOG(REIOS, "filename len: %d", temp[i - 1]); INFO_LOG(REIOS, "file LBA: %d", lba); INFO_LOG(REIOS, "file LEN: %d", len); @@ -82,24 +106,33 @@ bool reios_locate_bootfile(const char* bootfile="1ST_READ.BIN") { else libGDR_ReadSector(GetMemPtr(0x8c010000, 0), lba + 150, (len + 2047) / 2048, 2048); - if (false) { - FILE* f = fopen("z:\\1stboot.bin", "wb"); - fwrite(GetMemPtr(0x8c010000, 0), 1, len, f); - fclose(f); - } - delete[] temp; - bootfile_inited = true; + u8 data[24] = {0}; + // system id + for (u32 j = 0; j < 8; j++) + data[j] = _vmem_ReadMem8(0x0021a056 + j); + + // system properties + for (u32 j = 0; j < 5; j++) + data[8 + j] = _vmem_ReadMem8(0x0021a000 + j); + + // system settings + flash_syscfg_block syscfg; + verify(static_cast(flashrom)->ReadBlock(FLASH_PT_USER, FLASH_USER_SYSCFG, &syscfg)); + memcpy(&data[16], &syscfg.time_lo, 8); + + memcpy(GetMemPtr(0x8c000068, sizeof(data)), data, sizeof(data)); + return true; } + i += dir->length; } delete[] temp; return false; } -char ip_bin[256]; char reios_hardware_id[17]; char reios_maker_id[17]; char reios_device_info[17]; @@ -114,124 +147,115 @@ char reios_software_name[129]; char reios_bootfile[32]; bool reios_windows_ce = false; -bool pre_init = false; - -void reios_pre_init() -{ - if (libGDR_GetDiscType() == GdRom) { - base_fad = 45150; - descrambl = false; - } else { - u8 ses[6]; - libGDR_GetSessionInfo(ses, 0); - libGDR_GetSessionInfo(ses, ses[2]); - base_fad = (ses[3] << 16) | (ses[4] << 8) | (ses[5] << 0); - descrambl = true; - } - pre_init = true; -} - char* reios_disk_id() { - if (!pre_init) reios_pre_init(); + reios_pre_init(); - libGDR_ReadSector(GetMemPtr(0x8c008000, 0), base_fad, 256, 2048); - memset(ip_bin, 0, sizeof(ip_bin)); - memcpy(ip_bin, GetMemPtr(0x8c008000, 0), 256); - memcpy(&reios_hardware_id[0], &ip_bin[0], 16 * sizeof(char)); - memcpy(&reios_maker_id[0], &ip_bin[16], 16 * sizeof(char)); - memcpy(&reios_device_info[0], &ip_bin[32], 16 * sizeof(char)); - memcpy(&reios_area_symbols[0], &ip_bin[48], 8 * sizeof(char)); - memcpy(&reios_peripherals[0], &ip_bin[56], 8 * sizeof(char)); - memcpy(&reios_product_number[0], &ip_bin[64], 10 * sizeof(char)); - memcpy(&reios_product_version[0], &ip_bin[74], 6 * sizeof(char)); - memcpy(&reios_releasedate[0], &ip_bin[80], 16 * sizeof(char)); - memcpy(&reios_boot_filename[0], &ip_bin[96], 16 * sizeof(char)); - memcpy(&reios_software_company[0], &ip_bin[112], 16 * sizeof(char)); - memcpy(&reios_software_name[0], &ip_bin[128], 128 * sizeof(char)); + u8 buf[2048]; + libGDR_ReadSector(buf, base_fad, 1, sizeof(buf)); + memcpy(&reios_hardware_id[0], &buf[0], 16 * sizeof(char)); + memcpy(&reios_maker_id[0], &buf[16], 16 * sizeof(char)); + memcpy(&reios_device_info[0], &buf[32], 16 * sizeof(char)); + memcpy(&reios_area_symbols[0], &buf[48], 8 * sizeof(char)); + memcpy(&reios_peripherals[0], &buf[56], 8 * sizeof(char)); + memcpy(&reios_product_number[0], &buf[64], 10 * sizeof(char)); + memcpy(&reios_product_version[0], &buf[74], 6 * sizeof(char)); + memcpy(&reios_releasedate[0], &buf[80], 16 * sizeof(char)); + memcpy(&reios_boot_filename[0], &buf[96], 16 * sizeof(char)); + memcpy(&reios_software_company[0], &buf[112], 16 * sizeof(char)); + memcpy(&reios_software_name[0], &buf[128], 128 * sizeof(char)); reios_windows_ce = memcmp("0WINCEOS.BIN", &reios_boot_filename[0], 12) == 0; return reios_product_number; } -void reios_sys_system() { - debugf("reios_sys_system\n"); - +static void reios_sys_system() { u32 cmd = Sh4cntx.r[7]; switch (cmd) { case 0: //SYSINFO_INIT + { + debugf("reios_sys_system: SYSINFO_INIT"); + // 0x00-0x07: system_id + // 0x08-0x0c: system_props + // 0x0d-0x0f: padding (zeroed out) + // 0x10-0x17: settings (zeroed out) + u8 data[24] = {0}; + + // read system_id from 0x0001a056 + for (int i = 0; i < 8; i++) + data[i] = flashrom->Read8(0x1a056 + i); + + // read system_props from 0x0001a000 + for (int i = 0; i < 5; i++) + data[8 + i] = flashrom->Read8(0x1a000 + i); + + memcpy(GetMemPtr(0x8c000068, sizeof(data)), data, sizeof(data)); + Sh4cntx.r[0] = 0; - break; + } + break; case 2: //SYSINFO_ICON { - INFO_LOG(REIOS, "SYSINFO_ICON"); - /* - r4 = icon number (0-9, but only 5-9 seems to really be icons) - r5 = destination buffer (704 bytes in size) - */ + debugf("reios_sys_system: SYSINFO_ICON"); + // r4 = icon number (0-9, but only 5-9 seems to really be icons) + // r5 = destination buffer (704 bytes in size) Sh4cntx.r[0] = 704; } break; case 3: //SYSINFO_ID { - WriteMem32(SYSINFO_ID_ADDR + 0, 0xe1e2e3e4); - WriteMem32(SYSINFO_ID_ADDR + 4, 0xe5e6e7e8); - - Sh4cntx.r[0] = SYSINFO_ID_ADDR; + debugf("reios_sys_system: SYSINFO_ID"); +// WriteMem32(SYSINFO_ID_ADDR + 0, 0xe1e2e3e4); +// WriteMem32(SYSINFO_ID_ADDR + 4, 0xe5e6e7e8); +// +// Sh4cntx.r[0] = SYSINFO_ID_ADDR; + // TODO or this? + Sh4cntx.r[0] = 0x8c000068; } break; default: - INFO_LOG(REIOS, "unhandled: reios_sys_system"); + WARN_LOG(REIOS, "reios_sys_system: unhandled cmd %d", cmd); break; } } -void reios_sys_font() { - INFO_LOG(REIOS, "reios_sys_font"); +static void reios_sys_font() { + WARN_LOG(REIOS, "reios_sys_font"); } -void reios_sys_flashrom() { - debugf("reios_sys_flashrom\n"); - +static void reios_sys_flashrom() { u32 cmd = Sh4cntx.r[7]; - u32 flashrom_info[][2] = { - { 0 * 1024, 8 * 1024 }, - { 8 * 1024, 8 * 1024 }, - { 16 * 1024, 16 * 1024 }, - { 32 * 1024, 32 * 1024 }, - { 64 * 1024, 64 * 1024 }, - }; - - switch (cmd) { - case 0: // FLASHROM_INFO + switch (cmd) + { + case 0: // FLASHROM_INFO { /* - r4 = partition number(0 - 4) - r5 = pointer to two 32 bit integers to receive the result. - The first will be the offset of the partition start, in bytes from the start of the flashrom. - The second will be the size of the partition, in bytes. + r4 = partition number(0 - 4) + r5 = pointer to two 32 bit integers to receive the result. + The first will be the offset of the partition start, in bytes from the start of the flashrom. + The second will be the size of the partition, in bytes. - #define FLASHROM_PT_SYSTEM 0 /< \brief Factory settings (read-only, 8K) - #define FLASHROM_PT_RESERVED 1 /< \brief reserved (all 0s, 8K) - #define FLASHROM_PT_BLOCK_1 2 /< \brief Block allocated (16K) - #define FLASHROM_PT_SETTINGS 3 /< \brief Game settings (block allocated, 32K) - #define FLASHROM_PT_BLOCK_2 4 /< \brief Block allocated (64K) - */ + #define FLASHROM_PT_SYSTEM 0 /< \brief Factory settings (read-only, 8K) + #define FLASHROM_PT_RESERVED 1 /< \brief reserved (all 0s, 8K) + #define FLASHROM_PT_BLOCK_1 2 /< \brief Block allocated (16K) + #define FLASHROM_PT_SETTINGS 3 /< \brief Game settings (block allocated, 32K) + #define FLASHROM_PT_BLOCK_2 4 /< \brief Block allocated (64K) + */ u32 part = Sh4cntx.r[4]; u32 dest = Sh4cntx.r[5]; + debugf("reios_sys_flashrom: FLASHROM_INFO part %d dest %08x", part, dest); - u32* pDst = (u32*)GetMemPtr(dest, 8); + int* pDst = (int*)GetMemPtr(dest, 8); if (part <= 4) { - pDst[0] = flashrom_info[part][0]; - pDst[1] = flashrom_info[part][1]; - + static_cast(flashrom)->GetPartitionInfo(part, pDst, pDst + 1); + Sh4cntx.r[0] = 0; } else { @@ -240,25 +264,27 @@ void reios_sys_flashrom() { } break; - case 1: //FLASHROM_READ + case 1: //FLASHROM_READ { /* r4 = read start position, in bytes from the start of the flashrom r5 = pointer to destination buffer r6 = number of bytes to read */ - u32 offs = Sh4cntx.r[4]; + u32 offset = Sh4cntx.r[4]; u32 dest = Sh4cntx.r[5]; u32 size = Sh4cntx.r[6]; - memcpy(GetMemPtr(dest, size), flashrom + offs, size); + debugf("reios_sys_flashrom: FLASHROM_READ offs %x dest %08x size %x", offset, dest, size); + for (int i = 0; i < size; i++) + WriteMem8(dest++, flashrom->Read8(offset + i)); Sh4cntx.r[0] = size; } break; - case 2: //FLASHROM_WRITE + case 2: //FLASHROM_WRITE { /* r4 = write start position, in bytes from the start of the flashrom @@ -270,44 +296,46 @@ void reios_sys_flashrom() { u32 src = Sh4cntx.r[5]; u32 size = Sh4cntx.r[6]; + debugf("reios_sys_flashrom: FLASHROM_WRITE offs %x src %08x size %x", offs, src, size); u8* pSrc = GetMemPtr(src, size); for (int i = 0; i < size; i++) { - flashrom[offs + i] &= pSrc[i]; + flashrom->data[offs + i] &= pSrc[i]; } } break; - case 3: //FLASHROM_DELETE + case 3: //FLASHROM_DELETE { - u32 offs = Sh4cntx.r[4]; - u32 dest = Sh4cntx.r[5]; + u32 offset = Sh4cntx.r[4]; - u32 part = 5; + debugf("reios_sys_flashrom: FLASHROM_DELETE offs %x", offset); - for (int i = 0; i <= 4; i++) { - if (offs >= flashrom_info[i][0] && offs < (flashrom_info[i][0] + flashrom_info[i][1])) { - part = i; - break; + bool found = false; + + for (int part = 0; part < FLASH_PT_NUM; part++) + { + int part_offset; + int size; + static_cast(flashrom)->GetPartitionInfo(part, &part_offset, &size); + if (offset == part_offset) + { + found = true; + memset(flashrom->data + offset, 0xFF, size); } } - if (part <= 4) { - memset(flashrom + flashrom_info[part][0], 0xFF, flashrom_info[part][1]); - Sh4cntx.r[0] = 0; - } - else { - Sh4cntx.r[0] = -1; - } + Sh4cntx.r[0] = found ? 0 : -1; } break; - - default: - INFO_LOG(REIOS, "reios_sys_flashrom: not handled, %d", cmd); + + default: + WARN_LOG(REIOS, "reios_sys_flashrom: not handled, %d", cmd); + break; } } -void reios_sys_gd() { +static void reios_sys_gd() { gdrom_hle_op(); } @@ -318,7 +346,7 @@ void reios_sys_gd() { - gdGdcInitSystem, 3 - gdGdcGetDrvStat, 4 */ -void gd_do_bioscall() +static void gd_do_bioscall() { //looks like the "real" entrypoint for this on a dreamcast gdrom_hle_op(); @@ -364,23 +392,24 @@ void gd_do_bioscall() //gdGdcInitSystem } -void reios_sys_misc() { - INFO_LOG(REIOS, "reios_sys_misc - r7: 0x%08X, r4 0x%08X, r5 0x%08X, r6 0x%08X", Sh4cntx.r[7], Sh4cntx.r[4], Sh4cntx.r[5], Sh4cntx.r[6]); +static void reios_sys_misc() +{ + WARN_LOG(REIOS, "reios_sys_misc - r7: 0x%08X, r4 0x%08X, r5 0x%08X, r6 0x%08X", Sh4cntx.r[7], Sh4cntx.r[4], Sh4cntx.r[5], Sh4cntx.r[6]); Sh4cntx.r[0] = 0; } typedef void hook_fp(); -u32 hook_addr(hook_fp* fn); +static u32 hook_addr(hook_fp* fn); -void setup_syscall(u32 hook_addr, u32 syscall_addr) { +static void setup_syscall(u32 hook_addr, u32 syscall_addr) { WriteMem32(syscall_addr, hook_addr); WriteMem16(hook_addr, REIOS_OPCODE); - debugf("reios: Patching syscall vector %08X, points to %08X\n", syscall_addr, hook_addr); - debugf("reios: - address %08X: data %04X [%04X]\n", hook_addr, ReadMem16(hook_addr), REIOS_OPCODE); + debugf("Patching syscall vector %08X, points to %08X", syscall_addr, hook_addr); + debugf(" - address %08X: data %04X [%04X]", hook_addr, ReadMem16(hook_addr), REIOS_OPCODE); } -void reios_setup_state(u32 boot_addr) { +static void reios_setup_state(u32 boot_addr) { /* Post Boot registers from actual bios boot r @@ -451,7 +480,7 @@ void reios_setup_state(u32 boot_addr) { sh4rcb.cntx.old_fpscr.full = 0x00040001; } -void reios_setuo_naomi(u32 boot_addr) { +static void reios_setup_naomi(u32 boot_addr) { /* SR 0x60000000 0x00000001 FPSRC 0x00040001 @@ -571,7 +600,9 @@ void reios_setuo_naomi(u32 boot_addr) { sh4rcb.cntx.fpscr.full = 0x00040001; sh4rcb.cntx.old_fpscr.full = 0x00040001; } -void reios_boot() { + +static void reios_boot() +{ NOTICE_LOG(REIOS, "-----------------"); NOTICE_LOG(REIOS, "REIOS: Booting up"); NOTICE_LOG(REIOS, "-----------------"); @@ -593,14 +624,14 @@ void reios_boot() { if (settings.reios.ElfFile.size()) { if (!reios_loadElf(settings.reios.ElfFile)) { - msgboxf("Failed to open %s\n", MBX_ICONERROR, settings.reios.ElfFile.c_str()); + msgboxf("Failed to open %s", MBX_ICONERROR, settings.reios.ElfFile.c_str()); } reios_setup_state(0x8C010000); } else { if (settings.platform.system == DC_PLATFORM_DREAMCAST) { - if (!bootfile_inited) - msgboxf("Failed to locate bootfile", MBX_ICONERROR); + if (reios_boot_filename == NULL || !reios_locate_bootfile(reios_boot_filename)) + msgboxf("Failed to locate bootfile %s", MBX_ICONERROR, reios_boot_filename); reios_setup_state(0xac008300); } else { @@ -624,17 +655,17 @@ void reios_boot() { data_size = size; WriteMemBlock_nommu_ptr(0x0c020000, (u32*)CurrentCartridge->GetPtr(0, data_size), size); - reios_setuo_naomi(0x0c021000); + reios_setup_naomi(0x0c021000); } } } -map hooks; -map hooks_rev; +static std::map hooks; +static std::map hooks_rev; #define SYSCALL_ADDR_MAP(addr) ((addr & 0x1FFFFFFF) | 0x80000000) -void register_hook(u32 pc, hook_fp* fn) { +static void register_hook(u32 pc, hook_fp* fn) { hooks[SYSCALL_ADDR_MAP(pc)] = fn; hooks_rev[fn] = pc; } @@ -646,12 +677,12 @@ void DYNACALL reios_trap(u32 op) { u32 mapd = SYSCALL_ADDR_MAP(pc); - debugf("reios: dispatch %08X -> %08X\n", pc, mapd); + //debugf("dispatch %08X -> %08X", pc, mapd); hooks[mapd](); } -u32 hook_addr(hook_fp* fn) { +static u32 hook_addr(hook_fp* fn) { if (hooks_rev.count(fn)) return hooks_rev[fn]; else { @@ -661,7 +692,7 @@ u32 hook_addr(hook_fp* fn) { } } -bool reios_init(u8* rom, u8* flash) { +bool reios_init(u8* rom, MemChip* flash) { INFO_LOG(REIOS, "reios: Init"); @@ -689,9 +720,7 @@ bool reios_init(u8* rom, u8* flash) { } void reios_reset() { - pre_init = false; } void reios_term() { - } diff --git a/core/reios/reios.h b/core/reios/reios.h index 38b32a902..4b7c08dee 100644 --- a/core/reios/reios.h +++ b/core/reios/reios.h @@ -2,8 +2,9 @@ #define REIOS_H #include "types.h" +#include "hw/flashrom/flashrom.h" -bool reios_init(u8* rom, u8* flash); +bool reios_init(u8* rom, MemChip *flash); void reios_reset(); @@ -12,6 +13,7 @@ void reios_term(); void DYNACALL reios_trap(u32 op); char* reios_disk_id(); +extern char reios_device_info[17]; extern char reios_software_name[129]; extern char reios_product_number[11]; extern bool reios_windows_ce; diff --git a/core/reios/reios_elf.cpp b/core/reios/reios_elf.cpp index ff17c938d..bdadadde9 100644 --- a/core/reios/reios_elf.cpp +++ b/core/reios/reios_elf.cpp @@ -14,6 +14,7 @@ bool reios_loadElf(const string& elf) { size_t size = ftell(f); if (size > 16 * 1024 * 1024) { + fclose(f); return false; } @@ -21,37 +22,38 @@ bool reios_loadElf(const string& elf) { memset(elfFile, 0, size); fseek(f, 0, SEEK_SET); - fread(elfFile, 1, size, f); + size_t nread = fread(elfFile, 1, size, f); fclose(f); - int i; - bool phys = false; - - - if (elf_checkFile(elfFile) != 0) { + if (nread != size || elf_checkFile(elfFile) != 0) + { free(elfFile); return false; } - for (i = 0; i < elf_getNumProgramHeaders(elfFile); i++) { - /* Load that section */ - uint64_t dest, src; - size_t len; - if (phys) { + bool phys = false; + for (int i = 0; i < elf_getNumProgramHeaders(elfFile); i++) + { + // Load that section + uint64_t dest; + if (phys) dest = elf_getProgramHeaderPaddr(elfFile, i); - } - else { + else dest = elf_getProgramHeaderVaddr(elfFile, i); - } - len = elf_getProgramHeaderFileSize(elfFile, i); - src = (uint64_t)(uintptr_t)elfFile + elf_getProgramHeaderOffset(elfFile, i); - + size_t len = elf_getProgramHeaderFileSize(elfFile, i); + void *src = (u8 *)elfFile + elf_getProgramHeaderOffset(elfFile, i); u8* ptr = GetMemPtr(dest, len); - - memcpy((void*)ptr, (void*)(uintptr_t)src, len); + if (ptr == NULL) + { + WARN_LOG(REIOS, "Invalid load address for section %d: %08lx", i, dest); + continue; + } + DEBUG_LOG(REIOS, "Loading section %d to %08lx - %08lx", i, dest, dest + len - 1); + memcpy(ptr, src, len); ptr += len; - memset((void*)ptr, 0, elf_getProgramHeaderMemorySize(elfFile, i) - len); + memset(ptr, 0, elf_getProgramHeaderMemorySize(elfFile, i) - len); } + free(elfFile); return true; -} \ No newline at end of file +} diff --git a/core/rend/gui.cpp b/core/rend/gui.cpp index 8cdbe09c6..7a281787a 100644 --- a/core/rend/gui.cpp +++ b/core/rend/gui.cpp @@ -303,6 +303,7 @@ static void gui_start_game(const std::string& path) gui_state = Main; game_started = false; cfgSetVirtual("config", "image", ""); + cfgSetVirtual("reios", "ElfFile", ""); } } @@ -1240,6 +1241,9 @@ static void gui_display_settings() } if (ImGui::CollapsingHeader("Other", ImGuiTreeNodeFlags_DefaultOpen)) { + ImGui::Checkbox("HLE BIOS", &settings.bios.UseReios); + ImGui::SameLine(); + ShowHelpMarker("Use high-level BIOS emulation if BIOS files are not found"); #ifndef _ANDROID ImGui::Checkbox("Serial Console", &settings.debug.SerialConsole); ImGui::SameLine(); diff --git a/core/serialize.cpp b/core/serialize.cpp index c72dde5a9..a92a58068 100644 --- a/core/serialize.cpp +++ b/core/serialize.cpp @@ -88,9 +88,6 @@ extern u32 SB_FFST; extern MemChip *sys_rom; extern MemChip *sys_nvmem; -//./core/hw/gdrom/gdrom_response.o -extern u16 reply_11[] ; - //./core/hw/gdrom/gdromv3.o extern int gdrom_schid; extern signed int sns_asc; @@ -367,7 +364,7 @@ bool dc_serialize(void **data, unsigned int *total_size) sys_rom->Serialize(data, total_size); sys_nvmem->Serialize(data, total_size); - REICAST_SA(reply_11,16) ; + REICAST_S(GD_HardwareInfo); REICAST_S(sns_asc); @@ -651,7 +648,7 @@ static bool dc_unserialize_libretro(void **data, unsigned int *total_size) die("Naomi/Atomiswave libretro savestates are not supported"); REICAST_USA(sys_nvmem->data, sys_nvmem->size); - REICAST_USA(reply_11,16); + REICAST_US(GD_HardwareInfo); REICAST_US(sns_asc); REICAST_US(sns_ascq); @@ -1012,7 +1009,7 @@ bool dc_unserialize(void **data, unsigned int *total_size) sys_rom->Unserialize(data, total_size); sys_nvmem->Unserialize(data, total_size); - REICAST_USA(reply_11,16) ; + REICAST_US(GD_HardwareInfo); REICAST_US(sns_asc); REICAST_US(sns_ascq); diff --git a/core/types.h b/core/types.h index 45f1f3583..cd2b9c5b6 100644 --- a/core/types.h +++ b/core/types.h @@ -792,7 +792,7 @@ void libGDR_ReadSubChannel(u8 * buff, u32 format, u32 len); void libGDR_GetToc(u32* toc,u32 area); u32 libGDR_GetDiscType(); void libGDR_GetSessionInfo(u8* pout,u8 session); - +u32 libGDR_GetTrackNumber(u32 sector, u32& elapsed); // 0x00600000 - 0x006007FF [NAOMI] (modem area for dreamcast) u32 libExtDevice_ReadMem_A0_006(u32 addr,u32 size);