diff --git a/src/guest/bios/bios.c b/src/guest/bios/bios.c index 9c38b13e..c767f9ab 100644 --- a/src/guest/bios/bios.c +++ b/src/guest/bios/bios.c @@ -8,7 +8,6 @@ #include "guest/bios/syscalls.h" #include "guest/dreamcast.h" #include "guest/gdrom/gdrom.h" -#include "guest/gdrom/iso.h" #include "guest/rom/flash.h" #include "guest/sh4/sh4.h" #include "render/imgui.h" @@ -215,88 +214,51 @@ static int bios_boot(struct bios *bios) { const uint32_t BOOT1_ADDR = 0x8c008000; const uint32_t BOOT2_ADDR = 0x8c010000; const uint32_t SYSINFO_ADDR = 0x8c000068; - const int sector_fmt = GD_SECTOR_ANY; - const int sector_mask = GD_MASK_DATA; - const int sector_size = 2048; - uint8_t tmp[0x10000]; LOG_INFO("bios_boot using hle bootstrap"); - /* get the session for the main data track */ - struct gd_spi_session data_session; - gdrom_get_session(gd, 2, &data_session); - int data_fad = data_session.fad; - /* load ip.bin bootstrap */ { - int r = gdrom_read_sectors(gd, data_fad, 16, sector_fmt, sector_mask, tmp, - sizeof(tmp)); - if (!r) { + /* bootstrap occupies the first 16 sectors of the data track */ + struct gd_spi_session data_session; + gdrom_get_session(gd, 2, &data_session); + + uint8_t tmp[DISC_MAX_SECTOR_SIZE * 16]; + int read = gdrom_read_sectors(gd, data_session.fad, 16, GD_SECTOR_ANY, + GD_MASK_DATA, tmp, sizeof(tmp)); + if (!read) { + LOG_WARNING("bios_boot failed to copy IP.BIN"); return 0; } - as_memcpy_to_guest(space, BOOT1_ADDR, tmp, r); + + as_memcpy_to_guest(space, BOOT1_ADDR, tmp, read); } /* load 1st_read.bin into ram */ { - static const char *bootfile = "1ST_READ.BIN"; + const char *bootfile = "1ST_READ.BIN"; - /* read primary volume descriptor */ - int r = gdrom_read_sectors(gd, data_fad + ISO_PVD_SECTOR, 1, sector_fmt, - sector_mask, tmp, sizeof(tmp)); - if (!r) { - return 0; - } - - struct iso_pvd *pvd = (struct iso_pvd *)tmp; - CHECK(pvd->type == 1); - CHECK(memcmp(pvd->id, "CD001", 5) == 0); - CHECK(pvd->version == 1); - - /* check root directory for the bootfile */ - struct iso_dir *root = &pvd->root_directory_record; - int len = align_up(root->size.le, sector_size); - int fad = GDROM_PREGAP + root->extent.le; - int n = len / sector_size; - r = gdrom_read_sectors(gd, fad, n, sector_fmt, sector_mask, tmp, - sizeof(tmp)); - if (!r) { - return 0; - } - - uint8_t *ptr = tmp; - uint8_t *end = tmp + len; - - while (ptr < end) { - struct iso_dir *dir = (struct iso_dir *)ptr; - const char *filename = (const char *)(ptr + sizeof(*dir)); - - if (memcmp(filename, bootfile, strlen(bootfile)) == 0) { - break; - } - - /* dir entries always begin on an even byte */ - ptr = (uint8_t *)filename + dir->name_len; - ptr = (uint8_t *)align_up((intptr_t)ptr, (intptr_t)2); - } - - if (ptr == end) { - LOG_WARNING("bios_boot failed to find '%s'", bootfile); + int fad; + int len; + int found = gdrom_find_file(gd, bootfile, &fad, &len); + if (!found) { + LOG_WARNING("bios_boot failed to find %s", bootfile); return 0; } /* copy the bootfile into ram */ - struct iso_dir *dir = (struct iso_dir *)ptr; - fad = GDROM_PREGAP + dir->extent.le; - n = align_up(dir->size.le, sector_size) / sector_size; - r = gdrom_copy_sectors(gd, fad, sector_fmt, sector_mask, n, space, - BOOT2_ADDR); - if (!r) { + uint8_t *tmp = malloc(len); + int read = gdrom_read_bytes(gd, fad, len, tmp, len); + if (read != len) { + LOG_WARNING("bios_boot failed to copied %s", bootfile); + free(tmp); return 0; } - LOG_INFO("bios_boot found '%s' at fad=%d size=%d", bootfile, fad, - dir->size.le); + as_memcpy_to_guest(space, BOOT2_ADDR, tmp, read); + free(tmp); + + LOG_INFO("bios_boot found '%s' at fad=%d size=%d", bootfile, fad, len); } /* write system info */ diff --git a/src/guest/bios/syscalls.c b/src/guest/bios/syscalls.c index a07688ea..ba8d5035 100644 --- a/src/guest/bios/syscalls.c +++ b/src/guest/bios/syscalls.c @@ -134,20 +134,27 @@ static void bios_gdrom_mainloop(struct bios *bios) { switch (bios->cmd_code) { case GDC_PIOREAD: case GDC_DMAREAD: { - uint32_t fad = bios->params[0]; - uint32_t n = bios->params[1]; + int fad = bios->params[0]; + int num_sectors = bios->params[1]; uint32_t dst = bios->params[2]; uint32_t unknown = bios->params[3]; int fmt = GD_SECTOR_ANY; int mask = GD_MASK_DATA; - LOG_SYSCALL("GDC_DMAREAD fad=0x%x n=0x%x dst=0x%x unknown=0x%x", fad, n, - dst, unknown); + LOG_SYSCALL("GDC_DMAREAD fad=0x%x n=0x%x dst=0x%x unknown=0x%x", fad, + num_sectors, dst, unknown); /* dma read functionality changes somehow when this in non-zero */ CHECK_EQ(unknown, 0); - int read = gdrom_copy_sectors(gd, fad, fmt, mask, n, space, dst); + int read = 0; + uint8_t tmp[DISC_MAX_SECTOR_SIZE]; + + for (int i = fad; i < fad + num_sectors; i++) { + int n = gdrom_read_sectors(gd, i, 1, fmt, mask, tmp, sizeof(tmp)); + as_memcpy_to_guest(space, dst + read, tmp, n); + read += n; + } bios->result[2] = read; /* result[3] seems to signals if data is remaining, calculated by: diff --git a/src/guest/gdrom/disc.c b/src/guest/gdrom/disc.c index d5055ef5..24969e91 100644 --- a/src/guest/gdrom/disc.c +++ b/src/guest/gdrom/disc.c @@ -3,6 +3,101 @@ #include "core/string.h" #include "guest/gdrom/cdi.h" #include "guest/gdrom/gdi.h" +#include "guest/gdrom/iso.h" + +int disc_find_file(struct disc *disc, const char *filename, int *fad, + int *len) { + uint8_t tmp[0x10000]; + + /* get the session for the main data track */ + struct session *session = disc_get_session(disc, 1); + struct track *data_track = disc_get_track(disc, session->first_track); + + /* read primary volume descriptor */ + int read = disc_read_sectors(disc, data_track->fad + ISO_PVD_SECTOR, 1, + GD_SECTOR_ANY, GD_MASK_DATA, tmp, sizeof(tmp)); + if (!read) { + return 0; + } + + struct iso_pvd *pvd = (struct iso_pvd *)tmp; + CHECK(pvd->type == 1); + CHECK(memcmp(pvd->id, "CD001", 5) == 0); + CHECK(pvd->version == 1); + + /* check root directory for the file + FIXME recurse subdirectories */ + struct iso_dir *root = &pvd->root_directory_record; + int root_len = root->size.le; + int root_fad = GDROM_PREGAP + root->extent.le; + read = disc_read_bytes(disc, root_fad, root_len, tmp, sizeof(tmp)); + if (!read) { + return 0; + } + + uint8_t *ptr = tmp; + uint8_t *end = tmp + root_len; + + while (ptr < end) { + struct iso_dir *dir = (struct iso_dir *)ptr; + const char *name = (const char *)(ptr + sizeof(*dir)); + + if (memcmp(name, filename, strlen(filename)) == 0) { + break; + } + + /* dir entries always begin on an even byte */ + ptr = (uint8_t *)name + dir->name_len; + ptr = (uint8_t *)align_up((intptr_t)ptr, (intptr_t)2); + } + + if (ptr == end) { + return 0; + } + + struct iso_dir *dir = (struct iso_dir *)ptr; + *fad = GDROM_PREGAP + dir->extent.le; + *len = dir->size.le; + + return 1; +} + +int disc_read_bytes(struct disc *disc, int fad, int len, void *dst, + int dst_size) { + CHECK_LE(len, dst_size); + + uint8_t tmp[DISC_MAX_SECTOR_SIZE]; + int rem = len; + + while (rem) { + int n = disc->read_sectors(disc, fad, 1, GD_SECTOR_ANY, GD_MASK_DATA, tmp, + sizeof(tmp)); + CHECK(n); + + /* don't overrun */ + n = MIN(n, rem); + memcpy(dst, tmp, n); + + rem -= n; + dst += n; + fad++; + } + + return len; +} + +int disc_read_sectors(struct disc *disc, int fad, int num_sectors, + int sector_fmt, int sector_mask, void *dst, + int dst_size) { + return disc->read_sectors(disc, fad, num_sectors, sector_fmt, sector_mask, + dst, dst_size); +} + +void disc_get_toc(struct disc *disc, int area, struct track **first_track, + struct track **last_track, int *leadin_fad, + int *leadout_fad) { + disc->get_toc(disc, area, first_track, last_track, leadin_fad, leadout_fad); +} struct track *disc_lookup_track(struct disc *disc, int fad) { int num_tracks = disc_get_num_tracks(disc); @@ -28,19 +123,6 @@ struct track *disc_lookup_track(struct disc *disc, int fad) { return NULL; } -int disc_read_sectors(struct disc *disc, int fad, int num_sectors, - int sector_fmt, int sector_mask, void *dst, - int dst_size) { - return disc->read_sectors(disc, fad, num_sectors, sector_fmt, sector_mask, - dst, dst_size); -} - -void disc_get_toc(struct disc *disc, int area, struct track **first_track, - struct track **last_track, int *leadin_fad, - int *leadout_fad) { - disc->get_toc(disc, area, first_track, last_track, leadin_fad, leadout_fad); -} - struct track *disc_get_track(struct disc *disc, int n) { return disc->get_track(disc, n); } diff --git a/src/guest/gdrom/disc.h b/src/guest/gdrom/disc.h index 4c9df28b..4d263fea 100644 --- a/src/guest/gdrom/disc.h +++ b/src/guest/gdrom/disc.h @@ -66,10 +66,13 @@ int disc_get_num_sessions(struct disc *disc); struct session *disc_get_session(struct disc *disc, int n); int disc_get_num_tracks(struct disc *disc); struct track *disc_get_track(struct disc *disc, int n); +struct track *disc_lookup_track(struct disc *disc, int fad); +int disc_find_file(struct disc *disc, const char *filename, int *fad, int *len); void disc_get_toc(struct disc *disc, int area, struct track **first_track, struct track **last_track, int *leadin_fad, int *leadout_fad); int disc_read_sectors(struct disc *disc, int fad, int num_sectors, int sector_fmt, int sector_mask, void *dst, int dst_size); -struct track *disc_lookup_track(struct disc *disc, int fad); +int disc_read_bytes(struct disc *disc, int fad, int len, void *dst, + int dst_size); #endif diff --git a/src/guest/gdrom/gdrom.c b/src/guest/gdrom/gdrom.c index 5a912b79..e7a7f2f6 100644 --- a/src/guest/gdrom/gdrom.c +++ b/src/guest/gdrom/gdrom.c @@ -467,24 +467,14 @@ static void gdrom_event(struct gdrom *gd, enum gd_event ev, int arg) { cb(gd, arg); } -int gdrom_copy_sectors(struct gdrom *gd, int fad, int fmt, int mask, - int num_sectors, struct address_space *space, - uint32_t dst) { +int gdrom_read_bytes(struct gdrom *gd, int fad, int len, uint8_t *dst, + int dst_size) { if (!gd->disc) { - LOG_WARNING("gdrom_copy_sectors failed, no disc"); + LOG_WARNING("gdrom_read_sectors failed, no disc"); return 0; } - int read = 0; - uint8_t tmp[DISC_MAX_SECTOR_SIZE]; - - for (int i = fad; i < fad + num_sectors; i++) { - int n = disc_read_sectors(gd->disc, i, 1, fmt, mask, tmp, sizeof(tmp)); - as_memcpy_to_guest(space, dst + read, tmp, n); - read += n; - } - - return read; + return disc_read_bytes(gd->disc, fad, len, dst, dst_size); } int gdrom_read_sectors(struct gdrom *gd, int fad, int num_sectors, int fmt, @@ -496,11 +486,18 @@ int gdrom_read_sectors(struct gdrom *gd, int fad, int num_sectors, int fmt, LOG_GDROM("gdrom_read_sectors [%d, %d)", fad, fad + num_sectors); - int read = - disc_read_sectors(gd->disc, fad, num_sectors, fmt, mask, dst, dst_size); - CHECK(read); + return disc_read_sectors(gd->disc, fad, num_sectors, fmt, mask, dst, + dst_size); +} - return read; +int gdrom_find_file(struct gdrom *gd, const char *filename, int *fad, + int *len) { + if (!gd->disc) { + LOG_WARNING("gdrom_find_file failed, no disc"); + return 0; + } + + return disc_find_file(gd->disc, filename, fad, len); } void gdrom_get_subcode(struct gdrom *gd, int format, uint8_t *data, int size) { diff --git a/src/guest/gdrom/gdrom.h b/src/guest/gdrom/gdrom.h index f790bc51..80b9f293 100644 --- a/src/guest/gdrom/gdrom.h +++ b/src/guest/gdrom/gdrom.h @@ -4,7 +4,6 @@ #include "guest/gdrom/disc.h" #include "guest/gdrom/gdrom_types.h" -struct address_space; struct dreamcast; struct gdrom; @@ -24,10 +23,10 @@ void gdrom_get_toc(struct gdrom *gd, int area, struct gd_spi_toc *toc); void gdrom_get_session(struct gdrom *gd, int session, struct gd_spi_session *ses); void gdrom_get_subcode(struct gdrom *gd, int format, uint8_t *data, int size); +int gdrom_find_file(struct gdrom *gd, const char *filename, int *fad, int *len); int gdrom_read_sectors(struct gdrom *gd, int fad, int num_sectors, int fmt, int mask, uint8_t *dst, int dst_size); -int gdrom_copy_sectors(struct gdrom *gd, int fad, int fmt, int mask, - int num_sectors, struct address_space *space, - uint32_t dst); +int gdrom_read_bytes(struct gdrom *gd, int fad, int len, uint8_t *dst, + int dst_size); #endif