summaryrefslogtreecommitdiff
path: root/romdb.c
diff options
context:
space:
mode:
Diffstat (limited to 'romdb.c')
-rw-r--r--romdb.c449
1 files changed, 1 insertions, 448 deletions
diff --git a/romdb.c b/romdb.c
index 51fcf51..a220f6d 100644
--- a/romdb.c
+++ b/romdb.c
@@ -8,6 +8,7 @@
#include "menu.h"
#include "xband.h"
#include "realtec.h"
+#include "nor.h"
#define DOM_TITLE_START 0x120
#define DOM_TITLE_END 0x150
@@ -30,374 +31,6 @@ char const *save_type_name(uint8_t save_type)
return "SRAM";
}
-enum {
- I2C_IDLE,
- I2C_START,
- I2C_DEVICE_ACK,
- I2C_ADDRESS_HI,
- I2C_ADDRESS_HI_ACK,
- I2C_ADDRESS,
- I2C_ADDRESS_ACK,
- I2C_READ,
- I2C_READ_ACK,
- I2C_WRITE,
- I2C_WRITE_ACK
-};
-
-char * i2c_states[] = {
- "idle",
- "start",
- "device ack",
- "address hi",
- "address hi ack",
- "address",
- "address ack",
- "read",
- "read_ack",
- "write",
- "write_ack"
-};
-
-void eeprom_init(eeprom_state *state, uint8_t *buffer, uint32_t size)
-{
- state->slave_sda = 1;
- state->host_sda = state->scl = 0;
- state->buffer = buffer;
- state->size = size;
- state->state = I2C_IDLE;
-}
-
-void set_host_sda(eeprom_state *state, uint8_t val)
-{
- if (state->scl) {
- if (val & ~state->host_sda) {
- //low to high, stop condition
- state->state = I2C_IDLE;
- state->slave_sda = 1;
- } else if (~val & state->host_sda) {
- //high to low, start condition
- state->state = I2C_START;
- state->slave_sda = 1;
- state->counter = 8;
- }
- }
- state->host_sda = val;
-}
-
-void set_scl(eeprom_state *state, uint8_t val)
-{
- if (val & ~state->scl) {
- //low to high transition
- switch (state->state)
- {
- case I2C_START:
- case I2C_ADDRESS_HI:
- case I2C_ADDRESS:
- case I2C_WRITE:
- state->latch = state->host_sda | state->latch << 1;
- state->counter--;
- if (!state->counter) {
- switch (state->state & 0x7F)
- {
- case I2C_START:
- state->state = I2C_DEVICE_ACK;
- break;
- case I2C_ADDRESS_HI:
- state->address = state->latch << 8;
- state->state = I2C_ADDRESS_HI_ACK;
- break;
- case I2C_ADDRESS:
- state->address |= state->latch;
- state->state = I2C_ADDRESS_ACK;
- break;
- case I2C_WRITE:
- state->buffer[state->address] = state->latch;
- state->state = I2C_WRITE_ACK;
- break;
- }
- }
- break;
- case I2C_DEVICE_ACK:
- if (state->latch & 1) {
- state->state = I2C_READ;
- state->counter = 8;
- if (state->size < 256) {
- state->address = state->latch >> 1;
- }
- state->latch = state->buffer[state->address];
- } else {
- if (state->size < 256) {
- state->address = state->latch >> 1;
- state->state = I2C_WRITE;
- } else if (state->size < 4096) {
- state->address = (state->latch & 0xE) << 7;
- state->state = I2C_ADDRESS;
- } else {
- state->state = I2C_ADDRESS_HI;
- }
- state->counter = 8;
- }
- break;
- case I2C_ADDRESS_HI_ACK:
- state->state = I2C_ADDRESS;
- state->counter = 8;
- break;
- case I2C_ADDRESS_ACK:
- state->state = I2C_WRITE;
- state->address &= state->size-1;
- state->counter = 8;
- break;
- case I2C_READ:
- state->counter--;
- if (!state->counter) {
- state->state = I2C_READ_ACK;
- }
- break;
- case I2C_READ_ACK:
- state->state = I2C_READ;
- state->counter = 8;
- state->address++;
- //TODO: page mask
- state->address &= state->size-1;
- state->latch = state->buffer[state->address];
- break;
- case I2C_WRITE_ACK:
- state->state = I2C_WRITE;
- state->counter = 8;
- state->address++;
- //TODO: page mask
- state->address &= state->size-1;
- break;
- }
- } else if (~val & state->scl) {
- //high to low transition
- switch (state->state & 0x7F)
- {
- case I2C_DEVICE_ACK:
- case I2C_ADDRESS_HI_ACK:
- case I2C_ADDRESS_ACK:
- case I2C_READ_ACK:
- case I2C_WRITE_ACK:
- state->slave_sda = 0;
- break;
- case I2C_READ:
- state->slave_sda = state->latch >> 7;
- state->latch = state->latch << 1;
- break;
- default:
- state->slave_sda = 1;
- break;
- }
- }
- state->scl = val;
-}
-
-uint8_t get_sda(eeprom_state *state)
-{
- return state->host_sda & state->slave_sda;
-}
-
-enum {
- NOR_NORMAL,
- NOR_PRODUCTID,
- NOR_BOOTBLOCK
-};
-
-enum {
- NOR_CMD_IDLE,
- NOR_CMD_AA,
- NOR_CMD_55
-};
-
-//Technically this value shoudl be slightly different between NTSC and PAL
-//as it's defined as 200 micro-seconds, not in clock cycles
-#define NOR_WRITE_PAUSE 10690
-
-void nor_flash_init(nor_state *state, uint8_t *buffer, uint32_t size, uint32_t page_size, uint16_t product_id, uint8_t bus_flags)
-{
- state->buffer = buffer;
- state->page_buffer = malloc(page_size);
- memset(state->page_buffer, 0xFF, page_size);
- state->size = size;
- state->page_size = page_size;
- state->product_id = product_id;
- state->last_write_cycle = 0xFFFFFFFF;
- state->mode = NOR_NORMAL;
- state->cmd_state = NOR_CMD_IDLE;
- state->alt_cmd = 0;
- state->bus_flags = bus_flags;
-}
-
-void nor_run(nor_state *state, uint32_t cycle)
-{
- if (state->last_write_cycle == 0xFFFFFFFF) {
- return;
- }
- if (cycle - state->last_write_cycle >= NOR_WRITE_PAUSE) {
- state->last_write_cycle = 0xFFFFFFFF;
- for (uint32_t i = 0; i < state->page_size; i++) {
- state->buffer[state->current_page + i] = state->page_buffer[i];
- }
- memset(state->page_buffer, 0xFF, state->page_size);
- }
-}
-
-uint8_t nor_flash_read_b(uint32_t address, void *vcontext)
-{
- m68k_context *m68k = vcontext;
- genesis_context *gen = m68k->system;
- nor_state *state = &gen->nor;
- if (
- ((address & 1) && state->bus_flags == RAM_FLAG_EVEN) ||
- (!(address & 1) && state->bus_flags == RAM_FLAG_ODD)
- ) {
- return 0xFF;
- }
- if (state->bus_flags != RAM_FLAG_BOTH) {
- address = address >> 1;
- }
-
- nor_run(state, m68k->current_cycle);
- switch (state->mode)
- {
- case NOR_NORMAL:
- return state->buffer[address & (state->size-1)];
- break;
- case NOR_PRODUCTID:
- switch (address & (state->size - 1))
- {
- case 0:
- return state->product_id >> 8;
- case 1:
- return state->product_id;
- case 2:
- //TODO: Implement boot block protection
- return 0xFE;
- default:
- return 0xFE;
- }
- break;
- case NOR_BOOTBLOCK:
- break;
- }
- return 0xFF;
-}
-
-uint16_t nor_flash_read_w(uint32_t address, void *context)
-{
- uint16_t value = nor_flash_read_b(address, context) << 8;
- value |= nor_flash_read_b(address+1, context);
- return value;
-}
-
-void nor_write_byte(nor_state *state, uint32_t address, uint8_t value, uint32_t cycle)
-{
- switch(state->mode)
- {
- case NOR_NORMAL:
- if (state->last_write_cycle != 0xFFFFFFFF) {
- state->current_page = address & (state->size - 1) & ~(state->page_size - 1);
- }
- state->page_buffer[address & (state->page_size - 1)] = value;
- break;
- case NOR_PRODUCTID:
- break;
- case NOR_BOOTBLOCK:
- //TODO: Implement boot block protection
- state->mode = NOR_NORMAL;
- break;
- }
-}
-
-void *nor_flash_write_b(uint32_t address, void *vcontext, uint8_t value)
-{
- m68k_context *m68k = vcontext;
- genesis_context *gen = m68k->system;
- nor_state *state = &gen->nor;
- if (
- ((address & 1) && state->bus_flags == RAM_FLAG_EVEN) ||
- (!(address & 1) && state->bus_flags == RAM_FLAG_ODD)
- ) {
- return vcontext;
- }
- if (state->bus_flags != RAM_FLAG_BOTH) {
- address = address >> 1;
- }
-
- nor_run(state, m68k->current_cycle);
- switch (state->cmd_state)
- {
- case NOR_CMD_IDLE:
- if (value == 0xAA && (address & (state->size - 1)) == 0x5555) {
- state->cmd_state = NOR_CMD_AA;
- } else {
- nor_write_byte(state, address, value, m68k->current_cycle);
- state->cmd_state = NOR_CMD_IDLE;
- }
- break;
- case NOR_CMD_AA:
- if (value == 0x55 && (address & (state->size - 1)) == 0x2AAA) {
- state->cmd_state = NOR_CMD_55;
- } else {
- nor_write_byte(state, 0x5555, 0xAA, m68k->current_cycle);
- nor_write_byte(state, address, value, m68k->current_cycle);
- state->cmd_state = NOR_CMD_IDLE;
- }
- break;
- case NOR_CMD_55:
- if ((address & (state->size - 1)) == 0x5555) {
- if (state->alt_cmd) {
- switch(value)
- {
- case 0x10:
- puts("UNIMPLEMENTED: NOR flash erase");
- break;
- case 0x20:
- puts("UNIMPLEMENTED: NOR flash disable protection");
- break;
- case 0x40:
- state->mode = NOR_BOOTBLOCK;
- break;
- case 0x60:
- state->mode = NOR_PRODUCTID;
- break;
- }
- } else {
- switch(value)
- {
- case 0x80:
- state->alt_cmd = 1;
- break;
- case 0x90:
- state->mode = NOR_PRODUCTID;
- break;
- case 0xA0:
- puts("UNIMPLEMENTED: NOR flash enable protection");
- break;
- case 0xF0:
- state->mode = NOR_NORMAL;
- break;
- default:
- printf("Unrecognized unshifted NOR flash command %X\n", value);
- }
- }
- } else {
- nor_write_byte(state, 0x5555, 0xAA, m68k->current_cycle);
- nor_write_byte(state, 0x2AAA, 0x55, m68k->current_cycle);
- nor_write_byte(state, address, value, m68k->current_cycle);
- }
- state->cmd_state = NOR_CMD_IDLE;
- break;
- }
- return vcontext;
-}
-
-void *nor_flash_write_w(uint32_t address, void *vcontext, uint16_t value)
-{
- nor_flash_write_b(address, vcontext, value >> 8);
- return nor_flash_write_b(address + 1, vcontext, value);
-}
-
uint16_t read_sram_w(uint32_t address, m68k_context * context)
{
genesis_context * gen = context->system;
@@ -531,86 +164,6 @@ m68k_context * write_bank_reg_b(uint32_t address, m68k_context * context, uint8_
}
return context;
}
-eeprom_map *find_eeprom_map(uint32_t address, genesis_context *gen)
-{
- for (int i = 0; i < gen->num_eeprom; i++)
- {
- if (address >= gen->eeprom_map[i].start && address <= gen->eeprom_map[i].end) {
- return gen->eeprom_map + i;
- }
- }
- return NULL;
-}
-
-void * write_eeprom_i2c_w(uint32_t address, void * context, uint16_t value)
-{
- genesis_context *gen = ((m68k_context *)context)->system;
- eeprom_map *map = find_eeprom_map(address, gen);
- if (!map) {
- fatal_error("Could not find EEPROM map for address %X\n", address);
- }
- if (map->scl_mask) {
- set_scl(&gen->eeprom, (value & map->scl_mask) != 0);
- }
- if (map->sda_write_mask) {
- set_host_sda(&gen->eeprom, (value & map->sda_write_mask) != 0);
- }
- return context;
-}
-
-void * write_eeprom_i2c_b(uint32_t address, void * context, uint8_t value)
-{
- genesis_context *gen = ((m68k_context *)context)->system;
- eeprom_map *map = find_eeprom_map(address, gen);
- if (!map) {
- fatal_error("Could not find EEPROM map for address %X\n", address);
- }
-
- uint16_t expanded, mask;
- if (address & 1) {
- expanded = value;
- mask = 0xFF;
- } else {
- expanded = value << 8;
- mask = 0xFF00;
- }
- if (map->scl_mask & mask) {
- set_scl(&gen->eeprom, (expanded & map->scl_mask) != 0);
- }
- if (map->sda_write_mask & mask) {
- set_host_sda(&gen->eeprom, (expanded & map->sda_write_mask) != 0);
- }
- return context;
-}
-
-uint16_t read_eeprom_i2c_w(uint32_t address, void * context)
-{
- genesis_context *gen = ((m68k_context *)context)->system;
- eeprom_map *map = find_eeprom_map(address, gen);
- if (!map) {
- fatal_error("Could not find EEPROM map for address %X\n", address);
- }
- uint16_t ret = 0;
- if (map->sda_read_bit < 16) {
- ret = get_sda(&gen->eeprom) << map->sda_read_bit;
- }
- return ret;
-}
-
-uint8_t read_eeprom_i2c_b(uint32_t address, void * context)
-{
- genesis_context *gen = ((m68k_context *)context)->system;
- eeprom_map *map = find_eeprom_map(address, gen);
- if (!map) {
- fatal_error("Could not find EEPROM map for address %X\n", address);
- }
- uint8_t bit = address & 1 ? map->sda_read_bit : map->sda_read_bit - 8;
- uint8_t ret = 0;
- if (bit < 8) {
- ret = get_sda(&gen->eeprom) << bit;
- }
- return ret;
-}
tern_node *load_rom_db()
{