reios fixes

This commit is contained in:
Flyinghead 2019-07-30 19:04:51 +02:00
parent f23a3d3756
commit 6059831ec7
18 changed files with 1181 additions and 400 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

557
core/reios/iso9660.h Normal file
View File

@ -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:
*/

View File

@ -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() {
}

View File

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

View File

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

View File

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

View File

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

View File

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