From d37dc725c6752696cbf1621d87966cbbd738d101 Mon Sep 17 00:00:00 2001 From: Anthony Pesch Date: Thu, 20 Jul 2017 20:06:50 -0400 Subject: [PATCH] initial widescreen patching support --- CMakeLists.txt | 1 + src/emulator.c | 9 +--- src/guest/aica/aica.c | 2 +- src/guest/arm7/arm7.c | 2 +- src/guest/bios/bios.c | 19 +++------ src/guest/dreamcast.c | 1 + src/guest/gdrom/cdi.c | 65 +++++++++++----------------- src/guest/gdrom/disc.c | 90 +++++++++++++++++++++++++-------------- src/guest/gdrom/disc.h | 18 ++++++-- src/guest/gdrom/gdi.c | 43 +++++++------------ src/guest/gdrom/gdrom.c | 46 +++++++++++++------- src/guest/gdrom/gdrom.h | 7 ++- src/guest/gdrom/patch.c | 83 ++++++++++++++++++++++++++++++++++++ src/guest/gdrom/patch.h | 30 +++++++++++++ src/guest/gdrom/patch.inc | 22 ++++++++++ src/guest/pvr/pvr.c | 2 +- src/guest/pvr/ta.c | 2 +- 17 files changed, 297 insertions(+), 145 deletions(-) create mode 100644 src/guest/gdrom/patch.c create mode 100644 src/guest/gdrom/patch.h create mode 100644 src/guest/gdrom/patch.inc diff --git a/CMakeLists.txt b/CMakeLists.txt index ff63e155..47fe04e2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -197,6 +197,7 @@ set(RELIB_SOURCES src/guest/gdrom/disc.c src/guest/gdrom/gdi.c src/guest/gdrom/gdrom.c + src/guest/gdrom/patch.c src/guest/holly/holly.c src/guest/maple/controller.c src/guest/maple/maple.c diff --git a/src/emulator.c b/src/emulator.c index 42896c12..f46215a5 100644 --- a/src/emulator.c +++ b/src/emulator.c @@ -38,7 +38,6 @@ DEFINE_AGGREGATE_COUNTER(frames); DEFINE_PERSISTENT_OPTION_STRING(aspect_ratio, "stretch", "Video aspect ratio"); -DEFINE_PERSISTENT_OPTION_INT(widescreen_hack, 1, "Enable widescreen hacks"); static const char *aspect_ratios[] = { "stretch", "4:3", @@ -554,13 +553,6 @@ static void emu_debug_menu(struct emu *emu) { } } - igSeparator(); - - if (igMenuItem("widescreen hack", NULL, OPTION_widescreen_hack, 1)) { - OPTION_widescreen_hack = !OPTION_widescreen_hack; - LOG_WARNING("widescreen hack settings changed, restart to apply"); - } - igEndMenu(); } igEndMenu(); @@ -570,6 +562,7 @@ static void emu_debug_menu(struct emu *emu) { } bios_debug_menu(emu->dc->bios); + gdrom_debug_menu(emu->dc->gdrom); holly_debug_menu(emu->dc->holly); aica_debug_menu(emu->dc->aica); sh4_debug_menu(emu->dc->sh4); diff --git a/src/guest/aica/aica.c b/src/guest/aica/aica.c index a8b35d09..47262c7f 100644 --- a/src/guest/aica/aica.c +++ b/src/guest/aica/aica.c @@ -799,7 +799,7 @@ static void aica_toggle_recording(struct aica *aica) { static int aica_init(struct device *dev) { struct aica *aica = (struct aica *)dev; - aica->wave_ram = memory_translate(aica->memory, "aica wave ram", 0x00000000); + aica->wave_ram = memory_translate(aica->memory, "aica wave ram", 0x0); /* init channels */ { diff --git a/src/guest/arm7/arm7.c b/src/guest/arm7/arm7.c index 3e202ede..5a4c06ad 100644 --- a/src/guest/arm7/arm7.c +++ b/src/guest/arm7/arm7.c @@ -213,7 +213,7 @@ static int arm7_init(struct device *dev) { arm->jit = jit_create("arm7", arm->frontend, arm->backend, (struct jit_guest *)arm->guest); - arm->wave_ram = memory_translate(dc->memory, "aica wave ram", 0x00000000); + arm->wave_ram = memory_translate(dc->memory, "aica wave ram", 0x0); return 1; } diff --git a/src/guest/bios/bios.c b/src/guest/bios/bios.c index a2b74039..c2917bf8 100644 --- a/src/guest/bios/bios.c +++ b/src/guest/bios/bios.c @@ -217,7 +217,7 @@ static int bios_boot(struct bios *bios) { LOG_INFO("bios_boot using hle bootstrap"); - /* load ip.bin bootstrap */ + /* load IP.BIN bootstrap */ { /* bootstrap occupies the first 16 sectors of the data track */ struct gd_spi_session data_session; @@ -234,31 +234,22 @@ static int bios_boot(struct bios *bios) { as_memcpy_to_guest(space, BOOT1_ADDR, tmp, read); } - /* load 1st_read.bin into ram */ + /* load 1ST_READ.BIN into ram */ { - const char *bootfile = "1ST_READ.BIN"; - - 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; - } + int fad, len; + gdrom_get_bootfile(gd, &fad, &len); /* copy the bootfile into ram */ 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); + LOG_WARNING("bios_boot failed to copy bootfile"); free(tmp); return 0; } 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/dreamcast.c b/src/guest/dreamcast.c index 9d0fcf65..97deb76d 100644 --- a/src/guest/dreamcast.c +++ b/src/guest/dreamcast.c @@ -140,6 +140,7 @@ int dc_init(struct dreamcast *dc) { } } + /* initialize after devices in order to manipulate the boot and flash roms */ if (!bios_init(dc->bios)) { LOG_WARNING("failed to initialize bios"); return 0; diff --git a/src/guest/gdrom/cdi.c b/src/guest/gdrom/cdi.c index 05ae0123..b82f1176 100644 --- a/src/guest/gdrom/cdi.c +++ b/src/guest/gdrom/cdi.c @@ -34,54 +34,24 @@ struct cdi { int num_tracks; }; -static int cdi_read_sectors(struct disc *disc, int fad, int num_sectors, - int sector_fmt, int sector_mask, void *dst, - int dst_size) { +static void cdi_read_sector(struct disc *disc, struct track *track, int fad, + void *dst) { struct cdi *cdi = (struct cdi *)disc; - struct track *track = disc_lookup_track(disc, fad); - CHECK_NOTNULL(track); - CHECK(sector_fmt == GD_SECTOR_ANY || sector_fmt == track->sector_fmt); - CHECK(sector_mask == GD_MASK_DATA); - /* seek the to the starting fad */ int offset = track->file_offset + fad * track->sector_size; int res = fseek(cdi->fp, offset, SEEK_SET); CHECK_EQ(res, 0); /* only read the data portion of the track */ - int header_size, error_size, data_size; + res = fseek(cdi->fp, track->header_size, SEEK_CUR); + CHECK_EQ(res, 0); - if (track->sector_fmt == GD_SECTOR_CDDA) { - header_size = 0; - error_size = 0; - data_size = track->sector_size - header_size - error_size; - CHECK_EQ(data_size, 2352); - } else if (track->sector_fmt == GD_SECTOR_M2F1) { - header_size = 8; - error_size = 280; - data_size = track->sector_size - header_size - error_size; - CHECK_EQ(data_size, 2048); - } else { - CHECK(0); - } + res = (int)fread(dst, 1, track->data_size, cdi->fp); + CHECK_EQ(res, track->data_size); - int read = 0; - - for (int i = 0; i < num_sectors; i++) { - res = fseek(cdi->fp, header_size, SEEK_CUR); - CHECK_EQ(res, 0); - - CHECK_LE(read + data_size, dst_size); - res = (int)fread(dst + read, 1, data_size, cdi->fp); - CHECK_EQ(res, data_size); - read += res; - - res = fseek(cdi->fp, error_size, SEEK_CUR); - CHECK_EQ(res, 0); - } - - return read; + res = fseek(cdi->fp, track->error_size, SEEK_CUR); + CHECK_EQ(res, 0); } static void cdi_get_toc(struct disc *disc, int area, struct track **first_track, @@ -224,8 +194,25 @@ static int cdi_parse_track(struct disc *disc, uint32_t version, track->fad = pregap_length + lba; track->adr = 0; track->ctrl = sector_fmt == GD_SECTOR_CDDA ? 0 : 4; + track->sector_fmt = cdi_sector_formats[mode]; track->sector_size = sector_size; + if (track->sector_fmt == GD_SECTOR_CDDA) { + track->header_size = 0; + track->error_size = 0; + track->data_size = + track->sector_size - track->header_size - track->error_size; + CHECK_EQ(track->data_size, 2352); + } else if (track->sector_fmt == GD_SECTOR_M2F1) { + track->header_size = 8; + track->error_size = 280; + track->data_size = + track->sector_size - track->header_size - track->error_size; + CHECK_EQ(track->data_size, 2048); + } else { + LOG_FATAL("unexpected sector format %d", track->sector_fmt); + } + track->file_offset = data_offset - track->fad * track->sector_size; LOG_INFO("cdi_parse_track track=%d fad=%d off=%d mode=%s/%d", track->num, @@ -379,7 +366,7 @@ struct disc *cdi_create(const char *filename) { cdi->get_num_tracks = &cdi_get_num_tracks; cdi->get_track = &cdi_get_track; cdi->get_toc = &cdi_get_toc; - cdi->read_sectors = &cdi_read_sectors; + cdi->read_sector = &cdi_read_sector; struct disc *disc = (struct disc *)cdi; diff --git a/src/guest/gdrom/disc.c b/src/guest/gdrom/disc.c index 5b6391c1..fc93ffea 100644 --- a/src/guest/gdrom/disc.c +++ b/src/guest/gdrom/disc.c @@ -4,6 +4,7 @@ #include "guest/gdrom/cdi.h" #include "guest/gdrom/gdi.h" #include "guest/gdrom/iso.h" +#include "guest/gdrom/patch.h" /* meta information found in the ip.bin */ struct disc_meta { @@ -38,8 +39,8 @@ int disc_read_bytes(struct disc *disc, int fad, int len, void *dst, int rem = len; while (rem) { - int n = disc->read_sectors(disc, fad, 1, GD_SECTOR_ANY, GD_MASK_DATA, tmp, - sizeof(tmp)); + int n = disc_read_sectors(disc, fad, 1, GD_SECTOR_ANY, GD_MASK_DATA, tmp, + sizeof(tmp)); CHECK(n); /* don't overrun */ @@ -57,8 +58,29 @@ int disc_read_bytes(struct disc *disc, int fad, int len, void *dst, 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); + struct track *track = disc_lookup_track(disc, fad); + CHECK_NOTNULL(track); + CHECK(sector_fmt == GD_SECTOR_ANY || sector_fmt == track->sector_fmt); + CHECK(sector_mask == GD_MASK_DATA); + + int read = 0; + int endfad = fad + num_sectors; + int bootstart = disc->bootfad; + int bootend = disc->bootfad + (disc->bootlen / track->data_size); + + for (int i = fad; i < endfad; i++) { + CHECK_LE(read + track->data_size, dst_size); + disc->read_sector(disc, track, i, dst + read); + read += track->data_size; + } + + /* apply bootfile patches */ + if (bootstart <= endfad && fad <= bootend) { + int offset = (fad - bootstart) * track->data_size; + patch_bootfile(disc->id, dst, offset, read); + } + + return read; } int disc_find_file(struct disc *disc, const char *filename, int *fad, @@ -67,10 +89,10 @@ int disc_find_file(struct disc *disc, const char *filename, int *fad, /* 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); + struct track *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, + int read = disc_read_sectors(disc, track->fad + ISO_PVD_SECTOR, 1, GD_SECTOR_ANY, GD_MASK_DATA, tmp, sizeof(tmp)); if (!read) { return 0; @@ -164,31 +186,12 @@ int disc_get_num_sessions(struct disc *disc) { return disc->get_num_sessions(disc); } -void disc_destroy(struct disc *disc) { - disc->destroy(disc); -} - int disc_get_format(struct disc *disc) { return disc->get_format(disc); } -void disc_get_id(struct disc *disc, char *id, int size) { - struct disc_meta meta; - disc_get_meta(disc, &meta); - - char device_info[17]; - char product_number[11]; - char product_version[7]; - char name[129]; - strncpy_trim_spaces(device_info, meta.device_info, sizeof(meta.device_info)); - strncpy_trim_spaces(product_number, meta.product_number, - sizeof(meta.product_number)); - strncpy_trim_spaces(product_version, meta.product_version, - sizeof(meta.product_version)); - strncpy_trim_spaces(name, meta.name, sizeof(meta.name)); - - snprintf(id, size, "%s %s %s %s", name, product_number, product_version, - device_info); +void disc_destroy(struct disc *disc) { + disc->destroy(disc); } struct disc *disc_create(const char *filename) { @@ -200,11 +203,36 @@ struct disc *disc_create(const char *filename) { disc = gdi_create(filename); } - if (disc) { - char id[DISC_MAX_ID_SIZE]; - disc_get_id(disc, id, sizeof(id)); - LOG_INFO("disc_create %s", id); + if (!disc) { + return NULL; } + /* generate a unique id for the disc, and cache off info about the bootfile */ + struct disc_meta meta; + disc_get_meta(disc, &meta); + + char device_info[17]; + char product_number[11]; + char product_version[7]; + char bootname[17]; + char name[129]; + + strncpy_trim_spaces(device_info, meta.device_info, sizeof(meta.device_info)); + strncpy_trim_spaces(product_number, meta.product_number, + sizeof(meta.product_number)); + strncpy_trim_spaces(product_version, meta.product_version, + sizeof(meta.product_version)); + strncpy_trim_spaces(bootname, meta.bootname, sizeof(meta.bootname)); + strncpy_trim_spaces(name, meta.name, sizeof(meta.name)); + + snprintf(disc->id, sizeof(disc->id), "%s %s %s %s", name, product_number, + product_version, device_info); + + int found = disc_find_file(disc, bootname, &disc->bootfad, &disc->bootlen); + CHECK(found); + + LOG_INFO("disc_create %s bootfad=%d bootlen=%d", disc->id, disc->bootfad, + disc->bootlen); + return disc; } diff --git a/src/guest/gdrom/disc.h b/src/guest/gdrom/disc.h index c48d083e..d21184b2 100644 --- a/src/guest/gdrom/disc.h +++ b/src/guest/gdrom/disc.h @@ -11,11 +11,19 @@ struct track { int num; + /* frame adddress, equal to lba + 150 */ int fad; + /* type of information encoded in the sub q channel */ int adr; + /* type of track */ int ctrl; + /* sector info */ int sector_fmt; int sector_size; + int header_size; + int error_size; + int data_size; + /* backing file */ char filename[PATH_MAX]; int file_offset; }; @@ -28,6 +36,10 @@ struct session { }; struct disc { + char id[DISC_MAX_ID_SIZE]; + int bootfad; + int bootlen; + void (*destroy)(struct disc *); int (*get_format)(struct disc *); @@ -40,22 +52,22 @@ struct disc { void (*get_toc)(struct disc *, int, struct track **, struct track **, int *, int *); - int (*read_sectors)(struct disc *, int, int, int, int, void *, int); + void (*read_sector)(struct disc *, struct track *, int, void *); }; struct disc *disc_create(const char *filename); void disc_destroy(struct disc *disc); -void disc_get_id(struct disc *disc, char *id, int size); int disc_get_format(struct disc *disc); 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_find_file(struct disc *disc, const char *filename, int *fad, int *len); int disc_read_sectors(struct disc *disc, int fad, int num_sectors, int sector_fmt, int sector_mask, void *dst, int dst_size); int disc_read_bytes(struct disc *disc, int fad, int len, void *dst, diff --git a/src/guest/gdrom/gdi.c b/src/guest/gdrom/gdi.c index fae6c551..179eead2 100644 --- a/src/guest/gdrom/gdi.c +++ b/src/guest/gdrom/gdi.c @@ -11,16 +11,10 @@ struct gdi { int num_tracks; }; -static int gdi_read_sectors(struct disc *disc, int fad, int num_sectors, - int sector_fmt, int sector_mask, void *dst, - int dst_size) { +static void gdi_read_sector(struct disc *disc, struct track *track, int fad, + void *dst) { struct gdi *gdi = (struct gdi *)disc; - struct track *track = disc_lookup_track(disc, fad); - CHECK_NOTNULL(track); - CHECK(sector_fmt == GD_SECTOR_ANY || sector_fmt == track->sector_fmt); - CHECK(sector_mask == GD_MASK_DATA); - /* open the file backing the track */ int n = (int)(track - gdi->tracks); FILE *fp = gdi->files[n]; @@ -36,27 +30,14 @@ static int gdi_read_sectors(struct disc *disc, int fad, int num_sectors, CHECK_EQ(res, 0); /* only read the data portion of the track */ - int header_size = 16; - int error_size = 288; - int data_size = track->sector_size - header_size - error_size; - CHECK_EQ(data_size, 2048); + res = fseek(fp, track->header_size, SEEK_CUR); + CHECK_EQ(res, 0); - int read = 0; + res = (int)fread(dst, 1, track->data_size, fp); + CHECK_EQ(res, track->data_size); - for (int i = 0; i < num_sectors; i++) { - res = fseek(fp, header_size, SEEK_CUR); - CHECK_EQ(res, 0); - - CHECK_LE(read + data_size, dst_size); - res = (int)fread(dst + read, 1, data_size, fp); - CHECK_EQ(res, data_size); - read += res; - - res = fseek(fp, error_size, SEEK_CUR); - CHECK_EQ(res, 0); - } - - return read; + res = fseek(fp, track->error_size, SEEK_CUR); + CHECK_EQ(res, 0); } static void gdi_get_toc(struct disc *disc, int area, struct track **first_track, @@ -167,8 +148,14 @@ static int gdi_parse(struct disc *disc, const char *filename) { track->num = gdi->num_tracks; track->fad = lba + GDROM_PREGAP; track->ctrl = ctrl; + track->sector_fmt = GD_SECTOR_M1; track->sector_size = sector_size; + track->header_size = 16; + track->error_size = 288; + track->data_size = + track->sector_size - track->header_size - track->error_size; + track->file_offset = file_offset - track->fad * track->sector_size; snprintf(track->filename, sizeof(track->filename), "%s" PATH_SEPARATOR "%s", dirname, filename); @@ -215,7 +202,7 @@ struct disc *gdi_create(const char *filename) { gdi->get_num_tracks = &gdi_get_num_tracks; gdi->get_track = &gdi_get_track; gdi->get_toc = &gdi_get_toc; - gdi->read_sectors = &gdi_read_sectors; + gdi->read_sector = &gdi_read_sector; struct disc *disc = (struct disc *)gdi; diff --git a/src/guest/gdrom/gdrom.c b/src/guest/gdrom/gdrom.c index 763870ac..56606093 100644 --- a/src/guest/gdrom/gdrom.c +++ b/src/guest/gdrom/gdrom.c @@ -4,7 +4,9 @@ #include "guest/dreamcast.h" #include "guest/gdrom/gdrom_replies.inc" #include "guest/gdrom/gdrom_types.h" +#include "guest/gdrom/patch.h" #include "guest/holly/holly.h" +#include "render/imgui.h" #if 0 #define LOG_GDROM LOG_INFO @@ -490,16 +492,6 @@ int gdrom_read_sectors(struct gdrom *gd, int fad, int num_sectors, int fmt, dst_size); } -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) { CHECK_NOTNULL(gd->disc); CHECK_GE(size, GD_SPI_SCD_SIZE); @@ -640,12 +632,6 @@ void gdrom_get_drive_mode(struct gdrom *gd, struct gd_hw_info *info) { *info = gd->hw_info; } -void gdrom_get_disc_id(struct gdrom *gd, char *id, int size) { - CHECK_NOTNULL(gd->disc); - - disc_get_id(gd->disc, id, size); -} - void gdrom_dma_end(struct gdrom *gd) { LOG_GDROM("gd_dma_end"); } @@ -680,6 +666,20 @@ void gdrom_dma_begin(struct gdrom *gd) { LOG_GDROM("gd_dma_begin"); } +int gdrom_find_file(struct gdrom *gd, const char *filename, int *fad, + int *len) { + CHECK_NOTNULL(gd->disc); + + return disc_find_file(gd->disc, filename, fad, len); +} + +void gdrom_get_bootfile(struct gdrom *gd, int *fad, int *len) { + CHECK_NOTNULL(gd->disc); + + *fad = gd->disc->bootfad; + *len = gd->disc->bootlen; +} + void gdrom_set_disc(struct gdrom *gd, struct disc *disc) { if (gd->disc != disc) { if (gd->disc) { @@ -707,6 +707,20 @@ void gdrom_set_disc(struct gdrom *gd, struct disc *disc) { /* TODO how do GD_FEATURES, GD_INTREASON, GD_BYCTLLO and GD_BYCTLHI behave */ } +#ifdef HAVE_IMGUI +void gdrom_debug_menu(struct gdrom *gd) { + if (igBeginMainMenuBar()) { + if (igBeginMenu("GDROM", 1)) { + patch_debug_menu(); + + igEndMenu(); + } + + igEndMainMenuBar(); + } +} +#endif + void gdrom_destroy(struct gdrom *gd) { if (gd->disc) { disc_destroy(gd->disc); diff --git a/src/guest/gdrom/gdrom.h b/src/guest/gdrom/gdrom.h index 1e084e31..3d7e4a7d 100644 --- a/src/guest/gdrom/gdrom.h +++ b/src/guest/gdrom/gdrom.h @@ -10,12 +10,16 @@ struct gdrom; struct gdrom *gdrom_create(struct dreamcast *dc); void gdrom_destroy(struct gdrom *gd); +void gdrom_debug_menu(struct gdrom *gd); + void gdrom_set_disc(struct gdrom *gd, struct disc *disc); +void gdrom_get_bootfile(struct gdrom *gd, int *fad, int *len); +int gdrom_find_file(struct gdrom *gd, const char *filename, int *fad, int *len); + void gdrom_dma_begin(struct gdrom *gd); int gdrom_dma_read(struct gdrom *gd, uint8_t *data, int n); void gdrom_dma_end(struct gdrom *gd); -void gdrom_get_disc_id(struct gdrom *gd, char *id, int size); void gdrom_get_drive_mode(struct gdrom *gd, struct gd_hw_info *info); void gdrom_set_drive_mode(struct gdrom *gd, struct gd_hw_info *info); void gdrom_get_status(struct gdrom *gd, struct gd_spi_status *stat); @@ -24,7 +28,6 @@ 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_read_bytes(struct gdrom *gd, int fad, int len, uint8_t *dst, diff --git a/src/guest/gdrom/patch.c b/src/guest/gdrom/patch.c new file mode 100644 index 00000000..ad25e88b --- /dev/null +++ b/src/guest/gdrom/patch.c @@ -0,0 +1,83 @@ +#include "guest/gdrom/patch.h" +#include "core/assert.h" +#include "core/string.h" +#include "guest/memory.h" +#include "render/imgui.h" + +DEFINE_PERSISTENT_OPTION_INT(patch_widescreen, 1, "Apply widescreen patches"); + +#if 0 +#define LOG_PATCH LOG_INFO +#else +#define LOG_PATCH(...) +#endif + +#define DATA(...) \ + (uint8_t[]) { \ + __VA_ARGS__ \ + } + +#define HUNKS(...) \ + (struct patch_hunk[]) { \ + __VA_ARGS__ \ + } + +#define NUM_HUNKS(...) (sizeof(HUNKS(__VA_ARGS__)) / sizeof(struct patch_hunk)) + +#define HUNK(offset, ...) \ + { offset, DATA(__VA_ARGS__), sizeof(DATA(__VA_ARGS__)) } + +#define PATCH(game, desc, flags, ...) \ + {game, desc, flags, HUNKS(__VA_ARGS__), NUM_HUNKS(__VA_ARGS__)}, + +static struct patch patches[] = { +#include "guest/gdrom/patch.inc" +}; +static int num_patches = sizeof(patches) / sizeof(patches[0]); + +void patch_bootfile(const char *game, uint8_t *buffer, int offset, int size) { + for (int i = 0; i < num_patches; i++) { + struct patch *patch = &patches[i]; + + /* only apply patches for the current game */ + if (strcmp(patch->game, game)) { + continue; + } + + if (!(patch->flags & PATCH_BOOTFILE)) { + continue; + } + + if ((patch->flags & PATCH_WIDESCREEN) && !OPTION_patch_widescreen) { + continue; + } + + LOG_PATCH("patches_apply %s at 0x%x", patch->desc, offset); + + for (int j = 0; j < patch->num_hunks; j++) { + struct patch_hunk *hunk = &patch->hunks[j]; + + for (int k = 0; k < hunk->len; k++) { + int index = hunk->offset + k; + + if (index < offset || index >= offset + size) { + continue; + } + + buffer[index - offset] = hunk->data[k]; + } + } + } +} + +#ifdef HAVE_IMGUI +void patch_debug_menu() { + if (igBeginMenu("patches", 1)) { + if (igMenuItem("widescreen", NULL, OPTION_patch_widescreen, 1)) { + OPTION_patch_widescreen = !OPTION_patch_widescreen; + } + + igEndMenu(); + } +} +#endif diff --git a/src/guest/gdrom/patch.h b/src/guest/gdrom/patch.h new file mode 100644 index 00000000..bee29be7 --- /dev/null +++ b/src/guest/gdrom/patch.h @@ -0,0 +1,30 @@ +#ifndef PATCH_H +#define PATCH_H + +#include + +struct address_space; + +enum { + PATCH_BOOTFILE = 0x1, + PATCH_WIDESCREEN = 0x2, +}; + +struct patch_hunk { + int offset; + uint8_t *data; + int len; +}; + +struct patch { + char *game; + char *desc; + int flags; + struct patch_hunk *hunks; + int num_hunks; +}; + +void patch_debug_menu(); +void patch_bootfile(const char *game, uint8_t *data, int offset, int size); + +#endif diff --git a/src/guest/gdrom/patch.inc b/src/guest/gdrom/patch.inc new file mode 100644 index 00000000..9aa21c60 --- /dev/null +++ b/src/guest/gdrom/patch.inc @@ -0,0 +1,22 @@ +PATCH("DYNAMITE COP MK-51013 V1.005 7996 GD-ROM1/1", + "widescreen hack", + PATCH_BOOTFILE | PATCH_WIDESCREEN, + HUNK(0x00048eb0,0x39,0x8E,0xE3,0x3F), + HUNK(0x00048fb8,0x39,0x8E,0xE3,0x3F), + HUNK(0x00049100,0x39,0x8E,0xE3,0x3F), + HUNK(0x0004b590,0x39,0x8E,0xE3,0x3F), + HUNK(0x0006b93c,0x39,0x8E,0xE3,0x3F), + HUNK(0x0006bce0,0x39,0x8E,0xE3,0x3F), + HUNK(0x0006c0d0,0x39,0x8E,0xE3,0x3F), + HUNK(0x0006c21c,0x39,0x8E,0xE3,0x3F), + HUNK(0x0006eec4,0x39,0x8E,0xE3,0x3F), + HUNK(0x000723c0,0x39,0x8E,0xE3,0x3F), + HUNK(0x0007d568,0x39,0x8E,0xE3,0x3F)) + +PATCH("SONIC ADVENTURE MK-51000 V1.005 3B97 GD-ROM1/1", + "widescreen hack", + PATCH_BOOTFILE | PATCH_WIDESCREEN, + HUNK(0x00026fb8,0xF0,0xF5,0x88,0x8C,0xF4,0xF5,0x88,0x8C,0x94,0x3A,0x01,0x8C), + HUNK(0x00026fc4,0x80,0xEF,0x0A,0x8C,0x10,0xF6,0x88,0x8C,0x18,0xF6,0x88,0x8C), + HUNK(0x00600d70,0x80,0xEF,0x0A,0x8C,0xA8,0x35,0x67,0x8C,0xE6,0x2F,0x43,0x6E), + HUNK(0x00612200,0x80,0xEF,0x0A,0x8C,0x18,0x03,0x89,0x8C,0x59,0xF0,0x59,0xF1)) diff --git a/src/guest/pvr/pvr.c b/src/guest/pvr/pvr.c index b5f77e45..2a831e05 100644 --- a/src/guest/pvr/pvr.c +++ b/src/guest/pvr/pvr.c @@ -233,7 +233,7 @@ static int pvr_init(struct device *dev) { #undef PVR_REG pvr->palette_ram = (uint8_t *)pvr->PALETTE_RAM000; - pvr->video_ram = memory_translate(dc->memory, "video ram", 0x00000000); + pvr->video_ram = memory_translate(dc->memory, "video ram", 0x0); /* configure initial vsync interval */ pvr_reconfigure_spg(pvr); diff --git a/src/guest/pvr/ta.c b/src/guest/pvr/ta.c index 7d1cad32..e6a397ff 100644 --- a/src/guest/pvr/ta.c +++ b/src/guest/pvr/ta.c @@ -625,7 +625,7 @@ static int ta_init(struct device *dev) { struct ta *ta = (struct ta *)dev; struct dreamcast *dc = ta->dc; - ta->video_ram = memory_translate(dc->memory, "video ram", 0x00000000); + ta->video_ram = memory_translate(dc->memory, "video ram", 0x0); for (int i = 0; i < array_size(ta->contexts); i++) { struct tile_context *ctx = &ta->contexts[i];