First steps towards a HLE bios implementation

This is very simplistic, but can already boot and run many games

Known working so far
- Dead Or Alive 2 LE
- Head Hunter
- Marvel VS Capcom 2

Not working
- (Almost) all others
This commit is contained in:
Stefanos Kornilios Mitsis Poiitidis 2014-12-29 22:05:35 +01:00
parent 2f584aa68d
commit 25eee26ce5
11 changed files with 598 additions and 6 deletions

View File

@ -14,8 +14,8 @@
#include "hw/aica/aica_if.h"
//#include "naomi/naomi.h"
#include "types.h"
#include "hw/flashrom/flashrom.h"
#include "reios/reios.h"
RomChip sys_rom(BIOS_SIZE);
@ -55,6 +55,14 @@ void SaveRomFiles(const string& root)
sys_nvmem.Save(root, ROM_PREFIX, "nvmem.bin", "nvmem");
}
bool LoadHle(const string& root) {
if (!sys_nvmem.Load(root, ROM_PREFIX, "%nvmem.bin;%flash_wb.bin;%flash.bin;%flash.bin.bin", "nvram")) {
printf("No nvmem loaded\n");
}
return reios_init(sys_rom.data, sys_nvmem.data);
}
#if (DC_PLATFORM == DC_PLATFORM_NORMAL) || (DC_PLATFORM == DC_PLATFORM_DEV_UNIT) || (DC_PLATFORM == DC_PLATFORM_NAOMI) || (DC_PLATFORM == DC_PLATFORM_NAOMI2)
u32 ReadBios(u32 addr,u32 sz) { return sys_rom.Read(addr,sz); }

View File

@ -90,4 +90,5 @@ u32 GetRamPageFromAddress(u32 RamAddress);
bool LoadRomFiles(const string& root);
void SaveRomFiles(const string& root);
void SaveRomFiles(const string& root);
bool LoadHle(const string& root);

View File

@ -4,7 +4,7 @@
#include "dyna/decoder_opcodes.h"
#include "types.h"
#include "hw/sh4/dyna/shil.h"
#include "reios/reios.h"
OpCallFP* OpPtr[0x10000];
sh4_opcodelistentry* OpDesc[0x10000];
@ -124,7 +124,8 @@ sh4_opcodelistentry missing_opcode = {0,iNotImplemented,0,0,ReadWritePC,"missing
sh4_opcodelistentry opcodes[]=
{
//HLE
{0, reios_trap, Mask_none, REIOS_OPCODE, Branch_dir, "reios_trap", 100, 100, CO, fix_none },
//CPU
{dec_i0000_nnnn_0010_0011 ,i0000_nnnn_0010_0011 ,Mask_n ,0x0023 ,Branch_rel_d ,"braf <REG_N>" ,2,3,CO,fix_none}, //braf <REG_N>
{dec_i0000_nnnn_0000_0011 ,i0000_nnnn_0000_0011 ,Mask_n ,0x0003 ,Branch_rel_d ,"bsrf <REG_N>" ,2,3,CO,fix_none}, //bsrf <REG_N>

View File

@ -170,9 +170,12 @@ int dc_init(int argc,wchar* argv[])
int rv= 0;
if (!LoadRomFiles(GetPath("/data/")))
if (settings.bios.UseReios || !LoadRomFiles(GetPath("/data/")))
{
return -3;
if (!LoadHle(GetPath("/data/")))
return -3;
else
printf("Did not load bios, using reios\n");
}
#if !defined(HOST_NO_REC)
@ -248,6 +251,8 @@ void LoadSettings()
settings.pvr.rend = cfgLoadInt("config","pvr.rend",0);
#endif
settings.bios.UseReios = cfgLoadInt("config", "bios.UseReios", 0);
#if (HOST_OS != OS_LINUX || defined(_ANDROID) || defined(TARGET_PANDORA))
settings.aica.BufferSize=2048;
#else

194
core/reios/gdrom_hle.cpp Normal file
View File

@ -0,0 +1,194 @@
/*
Basic gdrom syscall emulation
Adapted from some (very) old pre-nulldc hle code
*/
#include <stdio.h>
#include "types.h"
#include "hw/sh4/sh4_if.h"
#include "hw/sh4/sh4_mem.h"
#include "gdrom_hle.h"
void GDROM_HLE_ReadSES(u32 addr)
{
u32 s = ReadMem32(addr + 0);
u32 b = ReadMem32(addr + 4);
u32 ba = ReadMem32(addr + 8);
u32 bb = ReadMem32(addr + 12);
printf("GDROM_HLE_ReadSES: %d, %d, %d, %d\n", s, b, ba, bb);
}
void GDROM_HLE_ReadTOC(u32 Addr)
{
u32 s = ReadMem32(Addr + 0);
u32 b = ReadMem32(Addr + 4);
u8 * pDst = GetMemPtr(b, 0);
//
//printf("GDROM READ TOC : %X %X \n\n", s, b);
libGDR_GetToc((u32*)pDst, s);
}
void GDROM_HLE_ReadDMA(u32 addr)
{
u32 s = ReadMem32(addr + 0x00);
u32 n = ReadMem32(addr + 0x04);
u32 b = ReadMem32(addr + 0x08);
u32 u = ReadMem32(addr + 0x0C);
u8 * pDst = GetMemPtr(b, 0);
//printf("GDROM:\tPIO READ Sector=%d, Num=%d, Buffer=0x%08X, Unk01=0x%08X\n", s, n, b, u);
libGDR_ReadSector(pDst, s, n, 2048);
}
void GDROM_HLE_ReadPIO(u32 addr)
{
u32 s = ReadMem32(addr + 0x00);
u32 n = ReadMem32(addr + 0x04);
u32 b = ReadMem32(addr + 0x08);
u32 u = ReadMem32(addr + 0x0C);
u8 * pDst = GetMemPtr(b, 0);
//printf("GDROM:\tPIO READ Sector=%d, Num=%d, Buffer=0x%08X, Unk01=0x%08X\n", s, n, b, u);
libGDR_ReadSector(pDst, s, 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);
printf("GDROM:\tGETSCD [0]=%d, [1]=%d, [2]=0x%08X, [3]=0x%08X\n", s, n, b, u);
}
#define r Sh4cntx.r
u32 SecMode[4];
inline static void GD_HLE_Command(u32 cc, u32 prm)
{
switch(cc)
{
case GDCC_GETTOC:
printf("GDROM:\t*FIXME* CMD GETTOC PRM:%X\n",cc,prm);
break;
case GDCC_GETTOC2:
GDROM_HLE_ReadTOC(r[5]);
break;
case GDCC_GETSES:
printf("GDROM:\tGETSES PRM:%X\n", cc, prm);
GDROM_HLE_ReadSES(r[5]);
break;
case GDCC_INIT:
printf("GDROM:\tCMD INIT PRM:%X\n",cc,prm);
break;
case GDCC_PIOREAD:
GDROM_HLE_ReadPIO(r[5]);
break;
case GDCC_DMAREAD:
//printf("GDROM:\tCMD DMAREAD PRM:%X\n",cc,prm);
GDROM_HLE_ReadDMA(r[5]);
break;
case GDCC_PLAY_SECTOR:
printf("GDROM:\tCMD PLAYSEC? PRM:%X\n",cc,prm);
break;
case GDCC_RELEASE:
printf("GDROM:\tCMD RELEASE? PRM:%X\n",cc,prm);
break;
case GDCC_STOP: printf("GDROM:\tCMD STOP PRM:%X\n",cc,prm); break;
case GDCC_SEEK: printf("GDROM:\tCMD SEEK PRM:%X\n",cc,prm); break;
case GDCC_PLAY: printf("GDROM:\tCMD PLAY PRM:%X\n",cc,prm); break;
case GDCC_PAUSE:printf("GDROM:\tCMD PAUSE PRM:%X\n",cc,prm); break;
case GDCC_READ:
printf("GDROM:\tCMD READ PRM:%X\n",cc,prm);
break;
case GDCC_GETSCD:
printf("GDROM:\tGETSCD PRM:%X\n",cc,prm);
GDCC_HLE_GETSCD(r[5]);
break;
default: printf("GDROM:\tUnknown GDROM CC:%X PRM:%X\n",cc,prm); break;
}
}
void gdrom_hle_op()
{
static bool bFlip=false; // only works for last cmd, might help somewhere
static u32 dwReqID=0xFFFFFFFF; // 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
//printf("\nGDROM:\tHLE SEND COMMAND CC:%X param ptr: %X\n",r[4],r[5]);
GD_HLE_Command(r[4],r[5]);
r[0] = --dwReqID; // RET Request ID
bFlip= true; // COMMAND IS COMPLETE
break;
case GDROM_CHECK_COMMAND: //
//printf("\nGDROM:\tHLE CHECK COMMAND REQID:%X param ptr: %X\n",r[4],r[5]);
r[0] = bFlip ? 2 : 0; // RET Finished : Invalid
bFlip= false; // INVALIDATE CHECK CMD
break;
// NO return, NO params
case GDROM_MAIN:
//printf("\nGDROM:\tHLE GDROM_MAIN\n");
break;
case GDROM_INIT: printf("\nGDROM:\tHLE GDROM_INIT\n"); break;
case GDROM_RESET: printf("\nGDROM:\tHLE GDROM_RESET\n"); break;
case GDROM_CHECK_DRIVE: //
// printf("\nGDROM:\tHLE GDROM_CHECK_DRIVE r4:%X\n",r[4],r[5]);
WriteMem32(r[4]+0,0x02); // STANDBY
WriteMem32(r[4]+4,0x80); // CDROM | 0x80 for GDROM
r[0]=0; // RET SUCCESS
break;
case GDROM_ABORT_COMMAND: //
printf("\nGDROM:\tHLE GDROM_ABORT_COMMAND r4:%X\n",r[4],r[5]);
r[0]=-1; // RET FAILURE
break;
case GDROM_SECTOR_MODE: //
printf("GDROM:\tHLE GDROM_SECTOR_MODE PTR_r4:%X\n",r[4]);
for(int i=0; i<4; i++) {
SecMode[i] = ReadMem32(r[4]+(i<<2));
printf("%08X%s",SecMode[i],((3==i) ? "\n" : "\t"));
}
r[0]=0; // RET SUCCESS
break;
default: printf("\nGDROM:\tUnknown SYSCALL: %X\n",r[7]); break;
}
}
else // MISC
{
printf("SYSCALL:\tSYSCALL: %X\n",r[7]);
}
}

36
core/reios/gdrom_hle.h Normal file
View File

@ -0,0 +1,36 @@
#pragma once
#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 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 CTOC_LBA(n) (n)
#define CTOC_ADR(n) (n<<24)
#define CTOC_CTRL(n) (n<<28)
#define CTOC_TRACK(n) (n<<16)
void gdrom_hle_op();

312
core/reios/reios.cpp Normal file
View File

@ -0,0 +1,312 @@
/*
Extremely primitive bios replacement
*/
#include "reios.h"
#include "gdrom_hle.h"
#include "hw\sh4\sh4_mem.h"
#include <map>
#define dc_bios_syscall_system 0x8C0000B0
#define dc_bios_syscall_font 0x8C0000B4
#define dc_bios_syscall_flashrom 0x8C0000B8
#define dc_bios_syscall_gd 0x8C0000BC
#define dc_bios_syscall_misc 0x8c0000E0
#define SYSINFO_ID_ADDR 0x8C001010
u8* biosrom;
u8* flashrom;
bool reios_locate_bootfile(const char* bootfile="1ST_READ.BIN") {
u8* temp = new u8[2048 * 1024];
libGDR_ReadSector(temp, 45150 + 16, 1024, 2048);
for (int i = 0; i < 2048 * 1023; i++) {
if (memcmp(temp+i, bootfile, strlen(bootfile)) == 0){
printf("Found %s at %06X\n", bootfile, i);
printf("filename len: %d\n", temp[i - 1]);
printf("file LBA: %d, %d\n", (u32&)temp[i - 33 + 2], (u32&)temp[i - 33 + 2 + 4]);
printf("file LEN: %d, %d\n", (u32&)temp[i - 33 + 10], (u32&)temp[i - 33 + 10 + 4]);
u32 lba = (u32&)temp[i - 33 + 2]; //should use the big endian one, but i'm lazy
u32 len = (u32&)temp[i - 33 + 10]; //should use the big endian one, but i'm lazy
libGDR_ReadSector(GetMemPtr(0x8c010000, 0), lba + 150, (len + 2047) / 2048, 2048);
delete[] temp;
return true;
}
}
delete[] temp;
return false;
}
char reios_bootfile[32];
const char* reios_locate_ip() {
libGDR_ReadSector(GetMemPtr(0x8c008000, 0), 45150, 16, 2048);
memset(reios_bootfile, 0, sizeof(reios_bootfile));
memcpy(reios_bootfile, GetMemPtr(0x8c008060, 0), 16);
for (int i = 15; i >= 0; i--) {
if (reios_bootfile[i] != ' ')
break;
reios_bootfile[i] = 0;
}
sh4rcb.cntx.pc = 0x8c008300;
return reios_bootfile;
}
void reios_sys_system() {
//printf("reios_sys_system\n");
u32 cmd = Sh4cntx.r[7];
switch (cmd) {
case 0: //SYSINFO_INIT
Sh4cntx.r[0] = 0;
break;
case 2: //SYSINFO_ICON
{
printf("SYSINFO_ICON\n");
/*
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;
}
break;
default:
printf("unhandled: reios_sys_system\n");
break;
}
}
void reios_sys_font() {
printf("reios_sys_font\n");
}
void reios_sys_flashrom() {
//printf("reios_sys_flashrom\n");
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
{
/*
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)
*/
u32 part = Sh4cntx.r[4];
u32 dest = Sh4cntx.r[5];
u32* pDst = (u32*)GetMemPtr(dest, 8);
if (part <= 4) {
pDst[0] = flashrom_info[part][0];
pDst[1] = flashrom_info[part][1];
Sh4cntx.r[0] = 0;
}
else {
Sh4cntx.r[0] = -1;
}
}
break;
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 dest = Sh4cntx.r[5];
u32 size = Sh4cntx.r[6];
memcpy(GetMemPtr(dest, size), flashrom + offs, size);
Sh4cntx.r[0] = size;
}
break;
case 2: //FLASHROM_WRITE
{
/*
r4 = write start position, in bytes from the start of the flashrom
r5 = pointer to source buffer
r6 = number of bytes to write
*/
u32 offs = Sh4cntx.r[4];
u32 src = Sh4cntx.r[5];
u32 size = Sh4cntx.r[6];
u8* pSrc = GetMemPtr(src, size);
for (int i = 0; i < size; i++) {
flashrom[offs + i] &= pSrc[i];
}
}
break;
case 3: //FLASHROM_DELETE
{
u32 offs = Sh4cntx.r[4];
u32 dest = Sh4cntx.r[5];
u32 part = 5;
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;
}
}
if (part <= 4) {
memset(flashrom + flashrom_info[part][0], 0xFF, flashrom_info[part][1]);
Sh4cntx.r[0] = 0;
}
else {
Sh4cntx.r[0] = -1;
}
}
break;
default:
printf("reios_sys_flashrom: not handled, %d\n", cmd);
}
}
void reios_sys_gd() {
gdrom_hle_op();
}
void reios_sys_misc() {
printf("reios_sys_misc - r7: 0x%08X, r4 0x%08X, r5 0x%08X, r6 0x%08X\n", 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);
void setup_syscall(u32 hook_addr, u32 syscall_addr) {
WriteMem32(syscall_addr, hook_addr);
WriteMem32(hook_addr, REIOS_OPCODE);
}
void reios_boot() {
//setup syscalls
//find boot file
//boot it
memset(GetMemPtr(0x8C000000, 0), 0xFF, 64 * 1024);
setup_syscall(hook_addr(&reios_sys_system), dc_bios_syscall_system);
setup_syscall(hook_addr(&reios_sys_font), dc_bios_syscall_font);
setup_syscall(hook_addr(&reios_sys_flashrom), dc_bios_syscall_flashrom);
setup_syscall(hook_addr(&reios_sys_gd), dc_bios_syscall_gd);
setup_syscall(hook_addr(&reios_sys_misc), dc_bios_syscall_misc);
//Infinitive loop for arm !
WriteMem32(0x80800000, 0xEAFFFFFE);
const char* bootfile = reios_locate_ip();
if (!reios_locate_bootfile(bootfile))
msgboxf("Failed to locate bootfile", MBX_ICONERROR);
}
map<u32, hook_fp*> hooks;
map<hook_fp*, u32> hooks_rev;
void register_hook(u32 pc, hook_fp* fn) {
hooks[pc] = fn;
hooks_rev[fn] = pc;
}
void DYNACALL reios_trap(u32 op) {
verify(op == REIOS_OPCODE);
u32 pc = sh4rcb.cntx.pc - 2;
sh4rcb.cntx.pc = sh4rcb.cntx.pr;
//printf("reios: dispatch %08X\n", pc);
hooks[pc]();
}
u32 hook_addr(hook_fp* fn) {
auto pos = hooks_rev.find(fn);
return pos != hooks_rev.end() ? pos->second : 0;
}
bool reios_init(u8* rom, u8* flash) {
biosrom = rom;
flashrom = flash;
u16* rom16 = (u16*)rom;
rom16[0] = REIOS_OPCODE;
register_hook(0xA0000000, reios_boot);
register_hook(0x8C001000, reios_sys_system);
register_hook(0x8C001002, reios_sys_font);
register_hook(0x8C001004, reios_sys_flashrom);
register_hook(0x8C001006, reios_sys_gd);
register_hook(0x8C001008, reios_sys_misc);
return true;
}
void reios_reset() {
}
void reios_term() {
}

12
core/reios/reios.h Normal file
View File

@ -0,0 +1,12 @@
#include "types.h"
bool reios_init(u8* rom, u8* flash);
void reios_reset();
void reios_term();
void DYNACALL reios_trap(u32 op);
#define REIOS_OPCODE 0x085B

View File

@ -590,6 +590,10 @@ struct RegisterStruct
struct settings_t
{
struct {
bool UseReios;
} bios;
struct
{
bool UseMipmaps;

View File

@ -157,6 +157,8 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Fast|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Fast|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\core\reios\gdrom_hle.cpp" />
<ClCompile Include="..\core\reios\reios.cpp" />
<ClCompile Include="..\core\rend\d3d11\d3d11.cpp" />
<ClCompile Include="..\core\rend\gles\gldraw.cpp" />
<ClCompile Include="..\core\rend\gles\gles.cpp" />
@ -286,6 +288,8 @@
<ClInclude Include="..\core\oslib\audiostream_rif.h" />
<ClInclude Include="..\core\oslib\oslib.h" />
<ClInclude Include="..\core\profiler\profiler.h" />
<ClInclude Include="..\core\reios\gdrom_hle.h" />
<ClInclude Include="..\core\reios\reios.h" />
<ClInclude Include="..\core\rend\gles\gles.h" />
<ClInclude Include="..\core\rend\rend.h" />
<ClInclude Include="..\core\rend\TexCache.h" />

View File

@ -399,6 +399,12 @@
<ClCompile Include="..\core\deps\coreio\coreio.cpp">
<Filter>deps\coreio</Filter>
</ClCompile>
<ClCompile Include="..\core\reios\reios.cpp">
<Filter>reios</Filter>
</ClCompile>
<ClCompile Include="..\core\reios\gdrom_hle.cpp">
<Filter>reios</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Filter Include="hw">
@ -518,6 +524,9 @@
<Filter Include="deps\coreio">
<UniqueIdentifier>{23cfa286-fe88-439d-89de-a6a5a23cacc9}</UniqueIdentifier>
</Filter>
<Filter Include="reios">
<UniqueIdentifier>{f614dd66-5d30-4548-a209-f857f95fb505}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\core\hw\aica\aica.h">
@ -868,6 +877,12 @@
<ClInclude Include="..\core\deps\coreio\coreio.h">
<Filter>deps\coreio</Filter>
</ClInclude>
<ClInclude Include="..\core\reios\reios.h">
<Filter>reios</Filter>
</ClInclude>
<ClInclude Include="..\core\reios\gdrom_hle.h">
<Filter>reios</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\core\deps\zlib\Makefile">