mirror of
https://github.com/libretro/blastem.git
synced 2026-11-07 10:15:58 -10:00
This repo has been sitting on the July 2022 state of upstream BlastEm. The sync brings in four years of upstream work, most importantly for this repo the DSL generated CPU cores: upstream's Makefile now switches to NEW_CORE automatically on any architecture that has no native code generator, and genesis.h picks up the generated m68k context in that configuration, which is what makes non-x86 builds possible at all. Only .gitlab-ci.yml and Makefile.libretro are kept from this repo, every other file is upstream's.
152 lines
4.0 KiB
C
152 lines
4.0 KiB
C
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include "romdb.h"
|
|
#include "genesis.h"
|
|
#include "util.h"
|
|
|
|
typedef struct {
|
|
uint8_t rom_space[512*1024];
|
|
uint8_t regs[3];
|
|
} realtec;
|
|
|
|
|
|
uint8_t realtec_detect(uint8_t *rom, uint32_t rom_size)
|
|
{
|
|
//All Realtec mapper games are 512KB total
|
|
if (rom_size != 512*1024) {
|
|
return 0;
|
|
}
|
|
return memcmp(rom + 0x7E100, "SEGA", 4) == 0;
|
|
}
|
|
|
|
static realtec *get_realtec(genesis_context *gen)
|
|
{
|
|
if (!gen->extra) {
|
|
gen->extra = gen->m68k->mem_pointers[0];
|
|
}
|
|
return gen->extra;
|
|
}
|
|
|
|
static void *realtec_write_b(uint32_t address, void *context, uint8_t value)
|
|
{
|
|
if (address & 1) {
|
|
return context;
|
|
}
|
|
m68k_context *m68k = context;
|
|
genesis_context *gen = m68k->system;
|
|
realtec *r = get_realtec(gen);
|
|
uint32_t offset = address >> 13;
|
|
if (offset < 3 && r->regs[offset] != value) {
|
|
r->regs[offset] = value;
|
|
//other regs are only 3 bits, so assume 3 for this one too
|
|
uint32_t size = (r->regs[1] & 0x7) << 17;
|
|
uint32_t start = (r->regs[2] & 7) << 17 | (r->regs[0] & 6) << 19;
|
|
if (!size || size > 512*1024) {
|
|
size = 512*1024;
|
|
}
|
|
for(uint32_t cur = 0; cur < 512*1024; cur += size)
|
|
{
|
|
if (start + size > 512*1024) {
|
|
memcpy(r->rom_space + cur, gen->cart + start/2, 512*1024-start);
|
|
//assume it wraps
|
|
memcpy(r->rom_space + cur + 512*1024-start, gen->cart, size - (512*1024-start));
|
|
} else {
|
|
memcpy(r->rom_space + cur, gen->cart + start/2, size);
|
|
}
|
|
}
|
|
m68k_invalidate_code_range(gen->m68k, 0, 0x400000);
|
|
}
|
|
return context;
|
|
}
|
|
|
|
static void *realtec_write_w(uint32_t address, void *context, uint16_t value)
|
|
{
|
|
return realtec_write_b(address, context, value >> 8);
|
|
}
|
|
|
|
void realtec_serialize(genesis_context *gen, serialize_buffer *buf)
|
|
{
|
|
realtec *r = get_realtec(gen);
|
|
save_buffer8(buf, r->regs, sizeof(r->regs));
|
|
}
|
|
|
|
void realtec_deserialize(deserialize_buffer *buf, genesis_context *gen)
|
|
{
|
|
realtec *r = get_realtec(gen);
|
|
for (int i = 0; i < sizeof(r->regs); i++)
|
|
{
|
|
realtec_write_b(i << 13, gen->m68k, load_int8(buf));
|
|
}
|
|
}
|
|
|
|
rom_info realtec_configure_rom(uint8_t *rom, uint32_t rom_size, memmap_chunk const *base_map, uint32_t base_chunks)
|
|
{
|
|
rom_info info = {0};
|
|
realtec *r = calloc(sizeof(realtec), 1);
|
|
for (uint32_t i = 0; i < 512*1024; i += 8*1024)
|
|
{
|
|
memcpy(r->rom_space + i, rom + 0x7E000, 8*1024);
|
|
}
|
|
byteswap_rom(512*1024, (uint16_t *)r->rom_space);
|
|
|
|
uint8_t *name_start = NULL, *name_end = NULL;
|
|
for (int i = 0x94; i < 0xE0; i++)
|
|
{
|
|
if (name_start) {
|
|
if (rom[i] < ' ' || rom[i] > 0x80 || !memcmp(rom+i, "ARE", 3) || !memcmp(rom+i, "are", 3)) {
|
|
name_end = rom+i;
|
|
break;
|
|
}
|
|
} else if (rom[i] > ' ' && rom[i] < 0x80 && rom[i] != ':') {
|
|
name_start = rom + i;
|
|
}
|
|
}
|
|
if (name_start && !name_end) {
|
|
name_end = rom + 0xE0;
|
|
}
|
|
if (name_end) {
|
|
while (name_end > name_start && name_end[-1] == ' ')
|
|
{
|
|
name_end--;
|
|
}
|
|
info.name = malloc(name_end-name_start+1);
|
|
memcpy(info.name, name_start, name_end-name_start);
|
|
info.name[name_end-name_start] = 0;
|
|
} else {
|
|
info.name = strdup("Realtec Game");
|
|
}
|
|
info.save_type = SAVE_NONE;
|
|
info.save_size = 0;
|
|
info.save_buffer = NULL;
|
|
info.num_eeprom = 0;
|
|
info.eeprom_map = NULL;
|
|
info.rom = rom;
|
|
info.rom_size = rom_size;
|
|
info.mapper_type = MAPPER_REALTEC;
|
|
info.is_save_lock_on = 0;
|
|
info.port1_override = info.port2_override = info.ext_override = info.mouse_mode = NULL;
|
|
info.map_chunks = base_chunks + 2;
|
|
info.map = calloc(sizeof(memmap_chunk), info.map_chunks);
|
|
info.map[0].mask = sizeof(r->rom_space)-1;
|
|
info.map[0].flags = MMAP_READ|MMAP_CODE|MMAP_PTR_IDX;
|
|
info.map[0].start = 0;
|
|
info.map[0].end = 0x400000;
|
|
info.map[0].buffer = r->rom_space;
|
|
info.map[0].write_16 = NULL;
|
|
info.map[0].read_16 = NULL;
|
|
info.map[0].write_8 = NULL;
|
|
info.map[0].read_8 = NULL;
|
|
info.map[1].mask = 0x7FFF;
|
|
info.map[1].flags = 0;
|
|
info.map[1].start = 0x400000;
|
|
info.map[1].end = 0x800000;
|
|
info.map[1].write_16 = realtec_write_w;
|
|
info.map[1].write_8 = realtec_write_b;
|
|
info.map[1].read_16 = NULL;
|
|
info.map[1].read_8 = NULL;
|
|
memcpy(info.map + 2, base_map, base_chunks * sizeof(memmap_chunk));
|
|
|
|
return info;
|
|
}
|