reios fixes
This commit is contained in:
parent
f23a3d3756
commit
6059831ec7
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 <="
|
||||
};
|
||||
};
|
||||
|
|
|
@ -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));
|
||||
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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); }
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 <stdio.h>
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
void GD_HLE_Command(u32 cc, u32 prm);
|
||||
|
|
|
@ -0,0 +1,557 @@
|
|||
/*
|
||||
Copyright (C) 2003-2008, 2012-2013
|
||||
Rocky Bernstein <rocky@gnu.org>
|
||||
Copyright (C) 2000 Herbert Valerio Riedel <hvr@gnu.org>
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef CDIO_ISO9660_H_
|
||||
#define CDIO_ISO9660_H_
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#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:
|
||||
<em>abcd</em>.<em>eee</em> ->
|
||||
<em>filename</em>.<em>ext</em>;<em>version#</em>
|
||||
|
||||
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:
|
||||
*/
|
|
@ -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 <map>
|
||||
|
||||
|
@ -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<DCFlashChip*>(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<DCFlashChip*>(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<DCFlashChip*>(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<u32, hook_fp*> hooks;
|
||||
map<hook_fp*, u32> hooks_rev;
|
||||
static std::map<u32, hook_fp*> hooks;
|
||||
static std::map<hook_fp*, u32> 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() {
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue