summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--backend.h3
-rw-r--r--debug.c7
-rw-r--r--romdb.h10
-rw-r--r--sms.c50
-rw-r--r--sms.h3
-rw-r--r--system.h10
-rw-r--r--vdp.c105
-rw-r--r--vdp.h1
8 files changed, 149 insertions, 40 deletions
diff --git a/backend.h b/backend.h
index ae80846..56c872e 100644
--- a/backend.h
+++ b/backend.h
@@ -76,6 +76,8 @@ typedef struct {
write_8_fun write_8;
} memmap_chunk;
+#include "system.h"
+
typedef struct {
uint32_t flags;
native_map_slot *native_code_map;
@@ -90,6 +92,7 @@ typedef struct {
code_ptr handle_code_write;
code_ptr handle_align_error_write;
code_ptr handle_align_error_read;
+ system_str_fun_r8 debug_cmd_handler;
uint32_t memmap_chunks;
uint32_t address_mask;
uint32_t max_address;
diff --git a/debug.c b/debug.c
index 4c7dcd9..d114531 100644
--- a/debug.c
+++ b/debug.c
@@ -523,7 +523,12 @@ z80_context * zdebugger(z80_context * context, uint16_t address)
break;
}
default:
- fprintf(stderr, "Unrecognized debugger command %s\n", input_buf);
+ if (
+ !context->options->gen.debug_cmd_handler
+ || !context->options->gen.debug_cmd_handler(&system->header, input_buf)
+ ) {
+ fprintf(stderr, "Unrecognized debugger command %s\n", input_buf);
+ }
break;
}
}
diff --git a/romdb.h b/romdb.h
index 846f44a..9a08275 100644
--- a/romdb.h
+++ b/romdb.h
@@ -13,7 +13,6 @@
#define SAVE_NONE 0xFF
#include "tern.h"
-#include "backend.h"
typedef struct {
uint32_t start;
@@ -35,7 +34,12 @@ typedef struct {
uint8_t latch;
} eeprom_state;
-typedef struct {
+
+typedef struct rom_info rom_info;
+
+#include "backend.h"
+
+struct rom_info {
char *name;
memmap_chunk *map;
uint8_t *save_buffer;
@@ -51,7 +55,7 @@ typedef struct {
uint16_t mapper_start_index;
uint8_t save_type;
uint8_t regions;
-} rom_info;
+};
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);
diff --git a/sms.c b/sms.c
index 2cb3dc7..170f2ce 100644
--- a/sms.c
+++ b/sms.c
@@ -62,7 +62,7 @@ static uint8_t vdp_read(uint32_t location, void *vcontext)
update_interrupts(sms);
return ret;
} else {
- return vdp_data_port_read(sms->vdp);
+ return vdp_data_port_read_pbc(sms->vdp);
}
}
@@ -104,6 +104,7 @@ static void *mapper_write(uint32_t location, void *vcontext, uint8_t value)
void *old_value;
sms->ram[location & (sizeof(sms->ram)-1)] = value;
location &= 3;
+ sms->bank_regs[location] = value;
if (location) {
uint32_t idx = location - 1;
old_value = z80->mem_pointers[idx];
@@ -113,11 +114,53 @@ static void *mapper_write(uint32_t location, void *vcontext, uint8_t value)
z80_invalidate_code_range(z80, idx ? idx * 0x4000 : 0x400, idx * 0x4000 + 0x4000);
}
} else {
- //TODO: implement me
+ old_value = z80->mem_pointers[2];
+ if (value & 8) {
+ //cartridge RAM is enabled
+ z80->mem_pointers[2] = sms->cart_ram + (value & 4 ? (SMS_CART_RAM_SIZE/2) : 0);
+ } else {
+ //cartridge RAM is disabled
+ z80->mem_pointers[2] = sms->rom + (sms->bank_regs[3] << 14 & (sms->rom_size-1));
+ }
+ if (old_value != z80->mem_pointers[2]) {
+ //invalidate any code we translated for the relevant bank
+ z80_invalidate_code_range(z80, 0x8000, 0xC000);
+ }
}
return vcontext;
}
+static void *cart_ram_write(uint32_t location, void *vcontext, uint8_t value)
+{
+ z80_context *z80 = vcontext;
+ sms_context *sms = z80->system;
+ if (sms->bank_regs[0] & 8) {
+ //cartridge RAM is enabled
+ location &= 0x3FFF;
+ z80->mem_pointers[2][location] = value;
+ z80_handle_code_write(0x8000 + location, z80);
+ }
+ return vcontext;
+}
+
+uint8_t debug_commands(system_header *system, char *input_buf)
+{
+ sms_context *sms = (sms_context *)system;
+ switch(input_buf[0])
+ {
+ case 'v':
+ if (input_buf[1] == 'r') {
+ vdp_print_reg_explain(sms->vdp);
+ } else if (input_buf[1] == 's') {
+ vdp_print_sprite_table(sms->vdp);
+ } else {
+ return 0;
+ }
+ break;
+ }
+ return 1;
+}
+
static memmap_chunk io_map[] = {
{0x00, 0x40, 0xFF, 0, 0, 0, NULL, NULL, NULL, NULL, memory_io_write},
{0x40, 0x80, 0xFF, 0, 0, 0, NULL, NULL, NULL, hv_read, sms_psg_write},
@@ -232,7 +275,7 @@ sms_context *alloc_configure_sms(void *rom, uint32_t rom_size, void *extra_rom,
memory_map[0] = (memmap_chunk){0x0000, 0x0400, 0xFFFF, 0, 0, MMAP_READ, rom, NULL, NULL, NULL, NULL};
memory_map[1] = (memmap_chunk){0x0400, 0x4000, 0xFFFF, 0, 0, MMAP_READ|MMAP_PTR_IDX|MMAP_CODE, NULL, NULL, NULL, NULL, NULL};
memory_map[2] = (memmap_chunk){0x4000, 0x8000, 0x3FFF, 0, 1, MMAP_READ|MMAP_PTR_IDX|MMAP_CODE, NULL, NULL, NULL, NULL, NULL};
- memory_map[3] = (memmap_chunk){0x8000, 0xC000, 0x3FFF, 0, 2, MMAP_READ|MMAP_PTR_IDX|MMAP_CODE, NULL, NULL, NULL, NULL, NULL};
+ memory_map[3] = (memmap_chunk){0x8000, 0xC000, 0x3FFF, 0, 2, MMAP_READ|MMAP_PTR_IDX|MMAP_CODE, NULL, NULL, NULL, NULL, cart_ram_write};
memory_map[4] = (memmap_chunk){0xC000, 0xFFFC, sizeof(sms->ram)-1, 0, 0, MMAP_READ|MMAP_WRITE|MMAP_CODE, sms->ram, NULL, NULL, NULL, NULL};
memory_map[5] = (memmap_chunk){0xFFFC, 0x10000, 0xFFFF, 0, 0, MMAP_READ, ram_reg_overlap, NULL, NULL, NULL, mapper_write};
} else {
@@ -246,6 +289,7 @@ sms_context *alloc_configure_sms(void *rom, uint32_t rom_size, void *extra_rom,
init_z80_opts(zopts, info_out->map, info_out->map_chunks, io_map, 4, 15, 0xFF);
sms->z80 = init_z80_context(zopts);
sms->z80->system = sms;
+ sms->z80->options->gen.debug_cmd_handler = debug_commands;
sms->rom = rom;
sms->rom_size = rom_size;
diff --git a/sms.h b/sms.h
index 6911dc4..91b215e 100644
--- a/sms.h
+++ b/sms.h
@@ -8,6 +8,7 @@
#include "io.h"
#define SMS_RAM_SIZE (8*1024)
+#define SMS_CART_RAM_SIZE (32*1024)
typedef struct {
system_header header;
@@ -21,6 +22,8 @@ typedef struct {
uint32_t normal_clock;
uint8_t should_return;
uint8_t ram[SMS_RAM_SIZE];
+ uint8_t bank_regs[4];
+ uint8_t cart_ram[SMS_CART_RAM_SIZE];
} sms_context;
sms_context *alloc_configure_sms(void *rom, uint32_t rom_size, void *extra_rom, uint32_t extra_rom_size, uint32_t opts, uint8_t force_region, rom_info *info_out);
diff --git a/system.h b/system.h
index d4e7ac3..587a4ea 100644
--- a/system.h
+++ b/system.h
@@ -1,8 +1,6 @@
#ifndef SYSTEM_H_
#define SYSTEM_H_
#include <stdint.h>
-#include "arena.h"
-#include "romdb.h"
typedef struct system_header system_header;
typedef struct system_media system_media;
@@ -21,12 +19,16 @@ typedef enum {
typedef void (*system_fun)(system_header *);
typedef uint16_t (*system_fun_r16)(system_header *);
-typedef void (*start_system_fun)(system_header *, char *);
+typedef void (*system_str_fun)(system_header *, char *);
+typedef uint8_t (*system_str_fun_r8)(system_header *, char *);
typedef void (*speed_system_fun)(system_header *, uint32_t);
+#include "arena.h"
+#include "romdb.h"
+
struct system_header {
system_header *next_context;
- start_system_fun start_context;
+ system_str_fun start_context;
system_fun resume_context;
system_fun load_save;
system_fun persist_save;
diff --git a/vdp.c b/vdp.c
index 42eb469..d53b04a 100644
--- a/vdp.c
+++ b/vdp.c
@@ -255,24 +255,42 @@ static void render_sprite_cells_mode4(vdp_context * context)
void vdp_print_sprite_table(vdp_context * context)
{
- uint16_t sat_address = (context->regs[REG_SAT] & 0x7F) << 9;
- uint16_t current_index = 0;
- uint8_t count = 0;
- do {
- uint16_t address = current_index * 8 + sat_address;
- uint16_t cache_address = current_index * 4;
- uint8_t height = ((context->sat_cache[cache_address+2] & 0x3) + 1) * 8;
- uint8_t width = (((context->sat_cache[cache_address+2] >> 2) & 0x3) + 1) * 8;
- int16_t y = ((context->sat_cache[cache_address] & 0x3) << 8 | context->sat_cache[cache_address+1]) & 0x1FF;
- int16_t x = ((context->vdpmem[address+ 6] & 0x3) << 8 | context->vdpmem[address + 7]) & 0x1FF;
- uint16_t link = context->sat_cache[cache_address+3] & 0x7F;
- uint8_t pal = context->vdpmem[address + 4] >> 5 & 0x3;
- uint8_t pri = context->vdpmem[address + 4] >> 7;
- uint16_t pattern = ((context->vdpmem[address + 4] << 8 | context->vdpmem[address + 5]) & 0x7FF) << 5;
- printf("Sprite %d: X=%d(%d), Y=%d(%d), Width=%u, Height=%u, Link=%u, Pal=%u, Pri=%u, Pat=%X\n", current_index, x, x-128, y, y-128, width, height, link, pal, pri, pattern);
- current_index = link;
- count++;
- } while (current_index != 0 && count < 80);
+ if (context->regs[REG_MODE_2] & BIT_MODE_5) {
+ uint16_t sat_address = (context->regs[REG_SAT] & 0x7F) << 9;
+ uint16_t current_index = 0;
+ uint8_t count = 0;
+ do {
+ uint16_t address = current_index * 8 + sat_address;
+ uint16_t cache_address = current_index * 4;
+ uint8_t height = ((context->sat_cache[cache_address+2] & 0x3) + 1) * 8;
+ uint8_t width = (((context->sat_cache[cache_address+2] >> 2) & 0x3) + 1) * 8;
+ int16_t y = ((context->sat_cache[cache_address] & 0x3) << 8 | context->sat_cache[cache_address+1]) & 0x1FF;
+ int16_t x = ((context->vdpmem[address+ 6] & 0x3) << 8 | context->vdpmem[address + 7]) & 0x1FF;
+ uint16_t link = context->sat_cache[cache_address+3] & 0x7F;
+ uint8_t pal = context->vdpmem[address + 4] >> 5 & 0x3;
+ uint8_t pri = context->vdpmem[address + 4] >> 7;
+ uint16_t pattern = ((context->vdpmem[address + 4] << 8 | context->vdpmem[address + 5]) & 0x7FF) << 5;
+ printf("Sprite %d: X=%d(%d), Y=%d(%d), Width=%u, Height=%u, Link=%u, Pal=%u, Pri=%u, Pat=%X\n", current_index, x, x-128, y, y-128, width, height, link, pal, pri, pattern);
+ current_index = link;
+ count++;
+ } while (current_index != 0 && count < 80);
+ } else {
+ uint16_t sat_address = (context->regs[REG_SAT] & 0x7E) << 7;
+ for (int i = 0; i < 64; i++)
+ {
+ uint8_t y = context->vdpmem[sat_address + (i ^ 1)];
+ if (y >= 0xD0) {
+ break;
+ }
+ uint8_t x = context->vdpmem[sat_address + 0x80 + i*2 + 1];
+ uint16_t tile_address = context->vdpmem[sat_address + 0x80 + i*2] * 32
+ + (context->regs[REG_STILE_BASE] << 11 & 0x2000);
+ if (context->regs[REG_MODE_2] & BIT_SPRITE_SZ) {
+ tile_address &= ~32;
+ }
+ printf("Sprite %d: X=%d, Y=%d, Pat=%X\n", i, x, y, tile_address);
+ }
+ }
}
#define VRAM_READ 0 //0000
@@ -344,17 +362,32 @@ void vdp_print_reg_explain(vdp_context * context)
context->regs[REG_MODE_3], context->regs[REG_MODE_3] & BIT_EINT_EN ? "enabled" : "disabled", context->regs[REG_MODE_3] & BIT_VSCROLL ? "2 cell" : "full",
hscroll[context->regs[REG_MODE_3] & 0x3],
context->regs[REG_MODE_4], context->regs[REG_MODE_4] & BIT_H40 ? 40 : 32, context->regs[REG_MODE_4] & BIT_HILIGHT ? "enabled" : "disabled");
- printf("\n**Table Group**\n"
- "02: %.2X | Scroll A Name Table: $%.4X\n"
- "03: %.2X | Window Name Table: $%.4X\n"
- "04: %.2X | Scroll B Name Table: $%.4X\n"
- "05: %.2X | Sprite Attribute Table: $%.4X\n"
- "0D: %.2X | HScroll Data Table: $%.4X\n",
- context->regs[REG_SCROLL_A], (context->regs[REG_SCROLL_A] & 0x38) << 10,
- context->regs[REG_WINDOW], (context->regs[REG_WINDOW] & (context->regs[REG_MODE_4] & BIT_H40 ? 0x3C : 0x3E)) << 10,
- context->regs[REG_SCROLL_B], (context->regs[REG_SCROLL_B] & 0x7) << 13,
- context->regs[REG_SAT], (context->regs[REG_SAT] & (context->regs[REG_MODE_4] & BIT_H40 ? 0x7E : 0x7F)) << 9,
- context->regs[REG_HSCROLL], (context->regs[REG_HSCROLL] & 0x3F) << 10);
+ if (context->regs[REG_MODE_2] & BIT_MODE_5) {
+ printf("\n**Table Group**\n"
+ "02: %.2X | Scroll A Name Table: $%.4X\n"
+ "03: %.2X | Window Name Table: $%.4X\n"
+ "04: %.2X | Scroll B Name Table: $%.4X\n"
+ "05: %.2X | Sprite Attribute Table: $%.4X\n"
+ "0D: %.2X | HScroll Data Table: $%.4X\n",
+ context->regs[REG_SCROLL_A], (context->regs[REG_SCROLL_A] & 0x38) << 10,
+ context->regs[REG_WINDOW], (context->regs[REG_WINDOW] & (context->regs[REG_MODE_4] & BIT_H40 ? 0x3C : 0x3E)) << 10,
+ context->regs[REG_SCROLL_B], (context->regs[REG_SCROLL_B] & 0x7) << 13,
+ context->regs[REG_SAT], (context->regs[REG_SAT] & (context->regs[REG_MODE_4] & BIT_H40 ? 0x7E : 0x7F)) << 9,
+ context->regs[REG_HSCROLL], (context->regs[REG_HSCROLL] & 0x3F) << 10);
+ } else {
+ printf("\n**Table Group**\n"
+ "02: %.2X | Background Name Table: $%.4X\n"
+ "05: %.2X | Sprite Attribute Table: $%.4X\n"
+ "06: %.2X | Sprite Tile Base: $%.4X\n"
+ "08: %.2X | Background X Scroll: %d\n"
+ "09: %.2X | Background Y Scroll: %d\n",
+ context->regs[REG_SCROLL_A], (context->regs[REG_SCROLL_A] & 0xE) << 10,
+ context->regs[REG_SAT], (context->regs[REG_SAT] & 0x7E) << 7,
+ context->regs[REG_STILE_BASE], (context->regs[REG_STILE_BASE] & 2) << 11,
+ context->regs[REG_X_SCROLL], context->regs[REG_X_SCROLL],
+ context->regs[REG_Y_SCROLL], context->regs[REG_Y_SCROLL]);
+
+ }
char * sizes[] = {"32", "64", "invalid", "128"};
printf("\n**Misc Group**\n"
"07: %.2X | Backdrop Color: $%X\n"
@@ -2330,6 +2363,20 @@ uint16_t vdp_data_port_read(vdp_context * context)
return context->prefetch;
}
+uint8_t vdp_data_port_read_pbc(vdp_context * context)
+{
+ if (context->flags & FLAG_PENDING) {
+ context->flags &= ~FLAG_PENDING;
+ //Should these be cleared here?
+ context->flags &= ~FLAG_READ_FETCHED;
+ context->flags2 &= ~FLAG2_READ_PENDING;
+ }
+ context->flags &= ~FLAG_READ_FETCHED;
+ //Should this happen after the prefetch or after the read?
+ context->address += context->regs[REG_AUTOINC];
+ return context->prefetch;
+}
+
uint16_t vdp_hv_counter_read(vdp_context * context)
{
if ((context->regs[REG_MODE_2] & BIT_MODE_5) && (context->regs[REG_MODE_1] & BIT_HVC_LATCH)) {
diff --git a/vdp.h b/vdp.h
index 878500c..59944b5 100644
--- a/vdp.h
+++ b/vdp.h
@@ -212,6 +212,7 @@ void vdp_data_port_write_pbc(vdp_context * context, uint8_t value);
void vdp_test_port_write(vdp_context * context, uint16_t value);
uint16_t vdp_control_port_read(vdp_context * context);
uint16_t vdp_data_port_read(vdp_context * context);
+uint8_t vdp_data_port_read_pbc(vdp_context * context);
uint16_t vdp_hv_counter_read(vdp_context * context);
uint16_t vdp_test_port_read(vdp_context * context);
void vdp_adjust_cycles(vdp_context * context, uint32_t deduction);