summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--genesis.c1
-rw-r--r--genesis.h1
-rw-r--r--i2c.c250
-rw-r--r--i2c.h22
-rw-r--r--nor.c204
-rw-r--r--nor.h10
-rw-r--r--romdb.c449
-rw-r--r--romdb.h14
9 files changed, 490 insertions, 463 deletions
diff --git a/Makefile b/Makefile
index 02d87f7..4339e2e 100644
--- a/Makefile
+++ b/Makefile
@@ -127,7 +127,7 @@ Z80OBJS=z80inst.o z80_to_x86.o
AUDIOOBJS=ym2612.o psg.o wave.o
CONFIGOBJS=config.o tern.o util.o
-MAINOBJS=blastem.o system.o genesis.o debug.o gdb_remote.o vdp.o render_sdl.o ppm.o io.o romdb.o hash.o menu.o xband.o realtec.o $(TERMINAL) $(CONFIGOBJS) gst.o $(M68KOBJS) $(TRANSOBJS) $(AUDIOOBJS)
+MAINOBJS=blastem.o system.o genesis.o debug.o gdb_remote.o vdp.o render_sdl.o ppm.o io.o romdb.o hash.o menu.o xband.o realtec.o i2c.o nor.o $(TERMINAL) $(CONFIGOBJS) gst.o $(M68KOBJS) $(TRANSOBJS) $(AUDIOOBJS)
ifeq ($(CPU),x86_64)
CFLAGS+=-DX86_64 -m64
diff --git a/genesis.c b/genesis.c
index aee7015..7ee975f 100644
--- a/genesis.c
+++ b/genesis.c
@@ -5,6 +5,7 @@
*/
#include "genesis.h"
#include "blastem.h"
+#include "nor.h"
#include <stdlib.h>
#include <ctype.h>
#include <time.h>
diff --git a/genesis.h b/genesis.h
index f2a0a5c..538f7f3 100644
--- a/genesis.h
+++ b/genesis.h
@@ -16,6 +16,7 @@
#include "io.h"
#include "romdb.h"
#include "arena.h"
+#include "i2c.h"
typedef struct genesis_context genesis_context;
diff --git a/i2c.c b/i2c.c
new file mode 100644
index 0000000..823c2cd
--- /dev/null
+++ b/i2c.c
@@ -0,0 +1,250 @@
+#include "genesis.h"
+#include "util.h"
+
+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;
+}
+
+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;
+}
diff --git a/i2c.h b/i2c.h
new file mode 100644
index 0000000..bc8accc
--- /dev/null
+++ b/i2c.h
@@ -0,0 +1,22 @@
+#ifndef I2C_H_
+#define I2C_H_
+
+typedef struct {
+ char *buffer;
+ uint32_t size;
+ uint16_t address;
+ uint8_t host_sda;
+ uint8_t slave_sda;
+ uint8_t scl;
+ uint8_t state;
+ uint8_t counter;
+ uint8_t latch;
+} eeprom_state;
+
+void eeprom_init(eeprom_state *state, uint8_t *buffer, uint32_t size);
+void * write_eeprom_i2c_w(uint32_t address, void * context, uint16_t value);
+void * write_eeprom_i2c_b(uint32_t address, void * context, uint8_t value);
+uint16_t read_eeprom_i2c_w(uint32_t address, void * context);
+uint8_t read_eeprom_i2c_b(uint32_t address, void * context);
+
+#endif //I2C_H_
diff --git a/nor.c b/nor.c
new file mode 100644
index 0000000..deae094
--- /dev/null
+++ b/nor.c
@@ -0,0 +1,204 @@
+#include "genesis.h"
+#include <stdlib.h>
+#include <string.h>
+
+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);
+}
diff --git a/nor.h b/nor.h
new file mode 100644
index 0000000..974363c
--- /dev/null
+++ b/nor.h
@@ -0,0 +1,10 @@
+#ifndef NOR_H_
+#define NOR_H_
+
+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);
+uint8_t nor_flash_read_b(uint32_t address, void *vcontext);
+uint16_t nor_flash_read_w(uint32_t address, void *context);
+void *nor_flash_write_b(uint32_t address, void *vcontext, uint8_t value);
+void *nor_flash_write_w(uint32_t address, void *vcontext, uint16_t value);
+
+#endif //NOR_H_
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()
{
diff --git a/romdb.h b/romdb.h
index 818a137..509a039 100644
--- a/romdb.h
+++ b/romdb.h
@@ -24,18 +24,6 @@ typedef struct {
} eeprom_map;
typedef struct {
- char *buffer;
- uint32_t size;
- uint16_t address;
- uint8_t host_sda;
- uint8_t slave_sda;
- uint8_t scl;
- uint8_t state;
- uint8_t counter;
- uint8_t latch;
-} eeprom_state;
-
-typedef struct {
uint8_t *buffer;
uint8_t *page_buffer;
uint32_t size;
@@ -83,8 +71,6 @@ tern_node *load_rom_db();
rom_info configure_rom(tern_node *rom_db, void *vrom, uint32_t rom_size, void *lock_on, uint32_t lock_on_size, memmap_chunk const *base_map, uint32_t base_chunks);
rom_info configure_rom_heuristics(uint8_t *rom, uint32_t rom_size, memmap_chunk const *base_map, uint32_t base_chunks);
uint8_t translate_region_char(uint8_t c);
-void eeprom_init(eeprom_state *state, uint8_t *buffer, uint32_t size);
-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);
char const *save_type_name(uint8_t save_type);
//Note: free_rom_info only frees things pointed to by a rom_info struct, not the struct itself
//this is because rom_info structs are typically stack allocated