Skip to content

Commit fae06b2

Browse files
committed
initial hle bios
1 parent e069ca0 commit fae06b2

File tree

12 files changed

+1255
-46
lines changed

12 files changed

+1255
-46
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ set(REDREAM_SOURCES
176176
src/guest/arm7/arm7.c
177177
src/guest/bios/bios.c
178178
src/guest/bios/flash.c
179+
src/guest/bios/syscalls.c
179180
src/guest/gdrom/cdi.c
180181
src/guest/gdrom/disc.c
181182
src/guest/gdrom/gdi.c

src/guest/bios/bios.c

Lines changed: 206 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,21 @@
33
#include "core/math.h"
44
#include "core/option.h"
55
#include "guest/aica/aica.h"
6+
#include "guest/bios/bios.h"
67
#include "guest/bios/flash.h"
8+
#include "guest/bios/syscalls.h"
79
#include "guest/dreamcast.h"
10+
#include "guest/gdrom/gdrom.h"
11+
#include "guest/gdrom/iso.h"
812
#include "guest/rom/flash.h"
13+
#include "guest/sh4/sh4.h"
914
#include "render/imgui.h"
1015

1116
DEFINE_OPTION_STRING(region, "america", "System region");
1217
DEFINE_OPTION_STRING(language, "english", "System language");
1318
DEFINE_OPTION_STRING(broadcast, "ntsc", "System broadcast mode");
1419

20+
/* system settings */
1521
static const char *regions[] = {
1622
"japan", "america", "europe",
1723
};
@@ -24,8 +30,22 @@ static const char *broadcasts[] = {
2430
"ntsc", "pal", "pal_m", "pal_n",
2531
};
2632

27-
struct bios {
28-
struct dreamcast *dc;
33+
/* address of syscall vectors */
34+
enum {
35+
VECTOR_SYSINFO = 0x0c0000b0,
36+
VECTOR_FONTROM = 0x0c0000b4,
37+
VECTOR_FLASHROM = 0x0c0000b8,
38+
VECTOR_GDROM = 0x0c0000bc,
39+
VECTOR_MENU = 0x0c0000e0,
40+
};
41+
42+
/* address of syscall entrypoints */
43+
enum {
44+
SYSCALL_SYSINFO = 0x0c003c00,
45+
SYSCALL_FONTROM = 0x0c003b80,
46+
SYSCALL_FLASHROM = 0x0c003d00,
47+
SYSCALL_GDROM = 0x0c001000,
48+
SYSCALL_MENU = 0x0c000800,
2949
};
3050

3151
static uint32_t bios_local_time() {
@@ -148,7 +168,7 @@ static void bios_validate_flash(struct bios *bios) {
148168

149169
/* validate partition 1 (reserved) */
150170
{
151-
LOG_INFO("bios_validate_flash resetting FLASH_PT_RESERVED");
171+
/* LOG_INFO("bios_validate_flash resetting FLASH_PT_RESERVED"); */
152172

153173
flash_erase_partition(flash, FLASH_PT_RESERVED);
154174
}
@@ -184,6 +204,131 @@ static void bios_validate_flash(struct bios *bios) {
184204
}
185205
}
186206

207+
static int bios_boot(struct bios *bios) {
208+
struct dreamcast *dc = bios->dc;
209+
struct flash *flash = dc->flash;
210+
struct gdrom *gd = dc->gdrom;
211+
struct sh4 *sh4 = dc->sh4;
212+
struct sh4_context *ctx = &sh4->ctx;
213+
struct address_space *space = sh4->memory_if->space;
214+
215+
const uint32_t BOOT1_ADDR = 0x8c008000;
216+
const uint32_t BOOT2_ADDR = 0x8c010000;
217+
const uint32_t SYSINFO_ADDR = 0x8c000068;
218+
const enum gd_secfmt secfmt = SECTOR_ANY;
219+
const enum gd_secmask secmask = MASK_DATA;
220+
const int secsz = 2048;
221+
uint8_t tmp[0x10000];
222+
223+
LOG_INFO("bios_boot using hle bootstrap");
224+
225+
/* load ip.bin bootstrap */
226+
{
227+
int fad = 45150;
228+
int n = 16;
229+
int r = gdrom_read_sectors(gd, fad, secfmt, secmask, n, tmp, sizeof(tmp));
230+
if (!r) {
231+
return 0;
232+
}
233+
as_memcpy_to_guest(space, BOOT1_ADDR, tmp, r);
234+
}
235+
236+
/* load 1st_read.bin into ram */
237+
{
238+
static const char *bootfile = "1ST_READ.BIN";
239+
240+
/* read primary volume descriptor */
241+
int fad = 45150 + ISO_PVD_SECTOR;
242+
int n = 1;
243+
int r = gdrom_read_sectors(gd, fad, secfmt, secmask, n, tmp, sizeof(tmp));
244+
if (!r) {
245+
return 0;
246+
}
247+
248+
struct iso_pvd *pvd = (struct iso_pvd *)tmp;
249+
CHECK(pvd->type == 1);
250+
CHECK(memcmp(pvd->id, "CD001", 5) == 0);
251+
CHECK(pvd->version == 1);
252+
253+
/* check root directory for the bootfile */
254+
struct iso_dir *root = &pvd->root_directory_record;
255+
int len = align_up(root->size.le, secsz);
256+
fad = GDROM_PREGAP + root->extent.le;
257+
n = len / secsz;
258+
r = gdrom_read_sectors(gd, fad, secfmt, secmask, n, tmp, sizeof(tmp));
259+
if (!r) {
260+
return 0;
261+
}
262+
263+
uint8_t *ptr = tmp;
264+
uint8_t *end = tmp + len;
265+
266+
while (ptr < end) {
267+
struct iso_dir *dir = (struct iso_dir *)ptr;
268+
const char *filename = (const char *)(ptr + sizeof(*dir));
269+
270+
if (memcmp(filename, bootfile, strlen(bootfile)) == 0) {
271+
break;
272+
}
273+
274+
/* dir entries always begin on an even byte */
275+
ptr = (uint8_t *)filename + dir->name_len;
276+
ptr = (uint8_t *)align_up((intptr_t)ptr, (intptr_t)2);
277+
}
278+
279+
if (ptr == end) {
280+
LOG_WARNING("bios_boot failed to find '%s'", bootfile);
281+
return 0;
282+
}
283+
284+
/* copy the bootfile into ram */
285+
struct iso_dir *dir = (struct iso_dir *)ptr;
286+
fad = GDROM_PREGAP + dir->extent.le;
287+
n = align_up(dir->size.le, secsz) / secsz;
288+
r = gdrom_copy_sectors(gd, fad, secfmt, secmask, n, space, BOOT2_ADDR);
289+
if (!r) {
290+
return 0;
291+
}
292+
293+
LOG_INFO("bios_boot found '%s' at fad=%d size=%d", bootfile, fad,
294+
dir->size.le);
295+
}
296+
297+
/* write system info */
298+
{
299+
uint8_t data[24] = {0};
300+
301+
/* read system id from 0x0001a056 */
302+
flash_read(flash, 0x1a056, &data[0], 8);
303+
304+
/* read system properties from 0x0001a000 */
305+
flash_read(flash, 0x1a000, &data[8], 5);
306+
307+
/* read system settings */
308+
struct flash_syscfg_block syscfg;
309+
int r = flash_read_block(flash, FLASH_PT_USER, FLASH_USER_SYSCFG, &syscfg);
310+
CHECK_EQ(r, 1);
311+
312+
memcpy(&data[16], &syscfg.time_lo, 8);
313+
314+
as_memcpy_to_guest(space, SYSINFO_ADDR, data, sizeof(data));
315+
}
316+
317+
/* write out syscall addresses to vectors */
318+
{
319+
as_write32(space, VECTOR_FONTROM, SYSCALL_FONTROM);
320+
as_write32(space, VECTOR_SYSINFO, SYSCALL_SYSINFO);
321+
as_write32(space, VECTOR_FLASHROM, SYSCALL_FLASHROM);
322+
as_write32(space, VECTOR_GDROM, SYSCALL_GDROM);
323+
as_write32(space, VECTOR_MENU, SYSCALL_MENU);
324+
}
325+
326+
/* start executing at license screen code inside of ip.bin */
327+
ctx->pc = 0xac008300;
328+
329+
return 1;
330+
}
331+
187332
void bios_debug_menu(struct bios *bios) {
188333
int changed = 0;
189334

@@ -238,11 +383,69 @@ void bios_debug_menu(struct bios *bios) {
238383
}
239384
}
240385

386+
int bios_invalid_instr(struct bios *bios) {
387+
struct dreamcast *dc = bios->dc;
388+
struct sh4_context *ctx = &dc->sh4->ctx;
389+
uint32_t pc = ctx->pc & 0x1cffffff;
390+
391+
if (pc == 0x0) {
392+
return bios_boot(bios);
393+
}
394+
395+
int handled = 1;
396+
397+
switch (pc) {
398+
case SYSCALL_FONTROM:
399+
bios_fontrom_vector(bios);
400+
break;
401+
402+
case SYSCALL_SYSINFO:
403+
bios_sysinfo_vector(bios);
404+
break;
405+
406+
case SYSCALL_FLASHROM:
407+
bios_flashrom_vector(bios);
408+
break;
409+
410+
case SYSCALL_GDROM:
411+
bios_gdrom_vector(bios);
412+
break;
413+
414+
case SYSCALL_MENU:
415+
bios_menu_vector(bios);
416+
break;
417+
418+
default:
419+
handled = 0;
420+
break;
421+
}
422+
423+
return handled;
424+
}
425+
241426
int bios_init(struct bios *bios) {
242427
bios_validate_flash(bios);
243428

244429
bios_override_flash_settings(bios);
245430

431+
/* this code enables a "hybrid" hle mode. in this mode, syscalls are patched
432+
to trap into their hle handlers, but the real bios can still be ran to
433+
test if bugs exist in the syscall emulation or bootstrap emulation */
434+
#if 0
435+
/* write out invalid instructions at syscall entry points. note, the boot rom
436+
does a bootstrap on startup which copies the boot rom into system ram. due
437+
to this, the invalid instructions are written to the original rom, not the
438+
system ram (or else, they would be overwritten by the bootstrap process) */
439+
struct boot *boot = bios->dc->boot;
440+
uint16_t invalid = 0x0;
441+
442+
boot_write(boot, SYSCALL_FONTROM, &invalid, 2);
443+
boot_write(boot, SYSCALL_SYSINFO, &invalid, 2);
444+
boot_write(boot, SYSCALL_FLASHROM, &invalid, 2);
445+
boot_write(boot, SYSCALL_GDROM, &invalid, 2);
446+
/*boot_write(boot, SYSCALL_MENU, &invalid, 2);*/
447+
#endif
448+
246449
return 1;
247450
}
248451

src/guest/bios/bios.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,26 @@
11
#ifndef BIOS_H
22
#define BIOS_H
33

4+
#include <stdint.h>
5+
46
struct dreamcast;
5-
struct bios;
7+
8+
struct bios {
9+
struct dreamcast *dc;
10+
11+
/* gdrom state */
12+
uint32_t status;
13+
uint32_t cmd_id;
14+
uint32_t cmd_code;
15+
uint32_t params[4];
16+
uint32_t result[4];
17+
};
618

719
struct bios *bios_create(struct dreamcast *dc);
820
void bios_destroy(struct bios *bios);
921

1022
int bios_init(struct bios *bios);
23+
int bios_invalid_instr(struct bios *bios);
1124

1225
void bios_debug_menu(struct bios *bios);
1326

0 commit comments

Comments
 (0)