mirror of https://github.com/inolen/redream.git
added disc_find_file helper
This commit is contained in:
parent
df67ffc63d
commit
df82a79f23
|
@ -8,7 +8,6 @@
|
||||||
#include "guest/bios/syscalls.h"
|
#include "guest/bios/syscalls.h"
|
||||||
#include "guest/dreamcast.h"
|
#include "guest/dreamcast.h"
|
||||||
#include "guest/gdrom/gdrom.h"
|
#include "guest/gdrom/gdrom.h"
|
||||||
#include "guest/gdrom/iso.h"
|
|
||||||
#include "guest/rom/flash.h"
|
#include "guest/rom/flash.h"
|
||||||
#include "guest/sh4/sh4.h"
|
#include "guest/sh4/sh4.h"
|
||||||
#include "render/imgui.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 BOOT1_ADDR = 0x8c008000;
|
||||||
const uint32_t BOOT2_ADDR = 0x8c010000;
|
const uint32_t BOOT2_ADDR = 0x8c010000;
|
||||||
const uint32_t SYSINFO_ADDR = 0x8c000068;
|
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");
|
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 */
|
/* load ip.bin bootstrap */
|
||||||
{
|
{
|
||||||
int r = gdrom_read_sectors(gd, data_fad, 16, sector_fmt, sector_mask, tmp,
|
/* bootstrap occupies the first 16 sectors of the data track */
|
||||||
sizeof(tmp));
|
struct gd_spi_session data_session;
|
||||||
if (!r) {
|
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;
|
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 */
|
/* load 1st_read.bin into ram */
|
||||||
{
|
{
|
||||||
static const char *bootfile = "1ST_READ.BIN";
|
const char *bootfile = "1ST_READ.BIN";
|
||||||
|
|
||||||
/* read primary volume descriptor */
|
int fad;
|
||||||
int r = gdrom_read_sectors(gd, data_fad + ISO_PVD_SECTOR, 1, sector_fmt,
|
int len;
|
||||||
sector_mask, tmp, sizeof(tmp));
|
int found = gdrom_find_file(gd, bootfile, &fad, &len);
|
||||||
if (!r) {
|
if (!found) {
|
||||||
return 0;
|
LOG_WARNING("bios_boot failed to find %s", bootfile);
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* copy the bootfile into ram */
|
/* copy the bootfile into ram */
|
||||||
struct iso_dir *dir = (struct iso_dir *)ptr;
|
uint8_t *tmp = malloc(len);
|
||||||
fad = GDROM_PREGAP + dir->extent.le;
|
int read = gdrom_read_bytes(gd, fad, len, tmp, len);
|
||||||
n = align_up(dir->size.le, sector_size) / sector_size;
|
if (read != len) {
|
||||||
r = gdrom_copy_sectors(gd, fad, sector_fmt, sector_mask, n, space,
|
LOG_WARNING("bios_boot failed to copied %s", bootfile);
|
||||||
BOOT2_ADDR);
|
free(tmp);
|
||||||
if (!r) {
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_INFO("bios_boot found '%s' at fad=%d size=%d", bootfile, fad,
|
as_memcpy_to_guest(space, BOOT2_ADDR, tmp, read);
|
||||||
dir->size.le);
|
free(tmp);
|
||||||
|
|
||||||
|
LOG_INFO("bios_boot found '%s' at fad=%d size=%d", bootfile, fad, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* write system info */
|
/* write system info */
|
||||||
|
|
|
@ -134,20 +134,27 @@ static void bios_gdrom_mainloop(struct bios *bios) {
|
||||||
switch (bios->cmd_code) {
|
switch (bios->cmd_code) {
|
||||||
case GDC_PIOREAD:
|
case GDC_PIOREAD:
|
||||||
case GDC_DMAREAD: {
|
case GDC_DMAREAD: {
|
||||||
uint32_t fad = bios->params[0];
|
int fad = bios->params[0];
|
||||||
uint32_t n = bios->params[1];
|
int num_sectors = bios->params[1];
|
||||||
uint32_t dst = bios->params[2];
|
uint32_t dst = bios->params[2];
|
||||||
uint32_t unknown = bios->params[3];
|
uint32_t unknown = bios->params[3];
|
||||||
int fmt = GD_SECTOR_ANY;
|
int fmt = GD_SECTOR_ANY;
|
||||||
int mask = GD_MASK_DATA;
|
int mask = GD_MASK_DATA;
|
||||||
|
|
||||||
LOG_SYSCALL("GDC_DMAREAD fad=0x%x n=0x%x dst=0x%x unknown=0x%x", fad, n,
|
LOG_SYSCALL("GDC_DMAREAD fad=0x%x n=0x%x dst=0x%x unknown=0x%x", fad,
|
||||||
dst, unknown);
|
num_sectors, dst, unknown);
|
||||||
|
|
||||||
/* dma read functionality changes somehow when this in non-zero */
|
/* dma read functionality changes somehow when this in non-zero */
|
||||||
CHECK_EQ(unknown, 0);
|
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;
|
bios->result[2] = read;
|
||||||
/* result[3] seems to signals if data is remaining, calculated by:
|
/* result[3] seems to signals if data is remaining, calculated by:
|
||||||
|
|
|
@ -3,6 +3,101 @@
|
||||||
#include "core/string.h"
|
#include "core/string.h"
|
||||||
#include "guest/gdrom/cdi.h"
|
#include "guest/gdrom/cdi.h"
|
||||||
#include "guest/gdrom/gdi.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) {
|
struct track *disc_lookup_track(struct disc *disc, int fad) {
|
||||||
int num_tracks = disc_get_num_tracks(disc);
|
int num_tracks = disc_get_num_tracks(disc);
|
||||||
|
@ -28,19 +123,6 @@ struct track *disc_lookup_track(struct disc *disc, int fad) {
|
||||||
return NULL;
|
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) {
|
struct track *disc_get_track(struct disc *disc, int n) {
|
||||||
return disc->get_track(disc, n);
|
return disc->get_track(disc, n);
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,10 +66,13 @@ int disc_get_num_sessions(struct disc *disc);
|
||||||
struct session *disc_get_session(struct disc *disc, int n);
|
struct session *disc_get_session(struct disc *disc, int n);
|
||||||
int disc_get_num_tracks(struct disc *disc);
|
int disc_get_num_tracks(struct disc *disc);
|
||||||
struct track *disc_get_track(struct disc *disc, int n);
|
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,
|
void disc_get_toc(struct disc *disc, int area, struct track **first_track,
|
||||||
struct track **last_track, int *leadin_fad, int *leadout_fad);
|
struct track **last_track, int *leadin_fad, int *leadout_fad);
|
||||||
int disc_read_sectors(struct disc *disc, int fad, int num_sectors,
|
int disc_read_sectors(struct disc *disc, int fad, int num_sectors,
|
||||||
int sector_fmt, int sector_mask, void *dst, int dst_size);
|
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
|
#endif
|
||||||
|
|
|
@ -467,24 +467,14 @@ static void gdrom_event(struct gdrom *gd, enum gd_event ev, int arg) {
|
||||||
cb(gd, arg);
|
cb(gd, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
int gdrom_copy_sectors(struct gdrom *gd, int fad, int fmt, int mask,
|
int gdrom_read_bytes(struct gdrom *gd, int fad, int len, uint8_t *dst,
|
||||||
int num_sectors, struct address_space *space,
|
int dst_size) {
|
||||||
uint32_t dst) {
|
|
||||||
if (!gd->disc) {
|
if (!gd->disc) {
|
||||||
LOG_WARNING("gdrom_copy_sectors failed, no disc");
|
LOG_WARNING("gdrom_read_sectors failed, no disc");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int read = 0;
|
return disc_read_bytes(gd->disc, fad, len, dst, dst_size);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int gdrom_read_sectors(struct gdrom *gd, int fad, int num_sectors, int fmt,
|
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);
|
LOG_GDROM("gdrom_read_sectors [%d, %d)", fad, fad + num_sectors);
|
||||||
|
|
||||||
int read =
|
return disc_read_sectors(gd->disc, fad, num_sectors, fmt, mask, dst,
|
||||||
disc_read_sectors(gd->disc, fad, num_sectors, fmt, mask, dst, dst_size);
|
dst_size);
|
||||||
CHECK(read);
|
}
|
||||||
|
|
||||||
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) {
|
void gdrom_get_subcode(struct gdrom *gd, int format, uint8_t *data, int size) {
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
#include "guest/gdrom/disc.h"
|
#include "guest/gdrom/disc.h"
|
||||||
#include "guest/gdrom/gdrom_types.h"
|
#include "guest/gdrom/gdrom_types.h"
|
||||||
|
|
||||||
struct address_space;
|
|
||||||
struct dreamcast;
|
struct dreamcast;
|
||||||
struct gdrom;
|
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,
|
void gdrom_get_session(struct gdrom *gd, int session,
|
||||||
struct gd_spi_session *ses);
|
struct gd_spi_session *ses);
|
||||||
void gdrom_get_subcode(struct gdrom *gd, int format, uint8_t *data, int size);
|
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 gdrom_read_sectors(struct gdrom *gd, int fad, int num_sectors, int fmt,
|
||||||
int mask, uint8_t *dst, int dst_size);
|
int mask, uint8_t *dst, int dst_size);
|
||||||
int gdrom_copy_sectors(struct gdrom *gd, int fad, int fmt, int mask,
|
int gdrom_read_bytes(struct gdrom *gd, int fad, int len, uint8_t *dst,
|
||||||
int num_sectors, struct address_space *space,
|
int dst_size);
|
||||||
uint32_t dst);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue