# HG changeset patch # User Michael Pavone # Date 1483591402 28800 # Node ID 6b0da602154474945c50311d9c210405eae7a59e # Parent 80ef49539550559bd240bfeda936bbd908f8536d Don't lock up CPU if performing a read with writes configured when in PBC mode. Allow access to VDP debug commands from Z80 debugger in PBC mode. Handle Mode 4 in VDP debug print functions diff -r 80ef49539550 -r 6b0da6021544 backend.h --- a/backend.h Tue Jan 03 23:03:30 2017 -0800 +++ b/backend.h Wed Jan 04 20:43:22 2017 -0800 @@ -76,6 +76,8 @@ 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 @@ 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 -r 80ef49539550 -r 6b0da6021544 debug.c --- a/debug.c Tue Jan 03 23:03:30 2017 -0800 +++ b/debug.c Wed Jan 04 20:43:22 2017 -0800 @@ -523,7 +523,12 @@ 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 -r 80ef49539550 -r 6b0da6021544 romdb.h --- a/romdb.h Tue Jan 03 23:03:30 2017 -0800 +++ b/romdb.h Wed Jan 04 20:43:22 2017 -0800 @@ -13,7 +13,6 @@ #define SAVE_NONE 0xFF #include "tern.h" -#include "backend.h" typedef struct { uint32_t start; @@ -35,7 +34,12 @@ 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 @@ 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 -r 80ef49539550 -r 6b0da6021544 sms.c --- a/sms.c Tue Jan 03 23:03:30 2017 -0800 +++ b/sms.c Wed Jan 04 20:43:22 2017 -0800 @@ -62,7 +62,7 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 -r 80ef49539550 -r 6b0da6021544 sms.h --- a/sms.h Tue Jan 03 23:03:30 2017 -0800 +++ b/sms.h Wed Jan 04 20:43:22 2017 -0800 @@ -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 @@ 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 -r 80ef49539550 -r 6b0da6021544 system.h --- a/system.h Tue Jan 03 23:03:30 2017 -0800 +++ b/system.h Wed Jan 04 20:43:22 2017 -0800 @@ -1,8 +1,6 @@ #ifndef SYSTEM_H_ #define SYSTEM_H_ #include -#include "arena.h" -#include "romdb.h" typedef struct system_header system_header; typedef struct system_media system_media; @@ -21,12 +19,16 @@ 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 -r 80ef49539550 -r 6b0da6021544 vdp.c --- a/vdp.c Tue Jan 03 23:03:30 2017 -0800 +++ b/vdp.c Wed Jan 04 20:43:22 2017 -0800 @@ -255,24 +255,42 @@ 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 @@ 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 @@ 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 -r 80ef49539550 -r 6b0da6021544 vdp.h --- a/vdp.h Tue Jan 03 23:03:30 2017 -0800 +++ b/vdp.h Wed Jan 04 20:43:22 2017 -0800 @@ -212,6 +212,7 @@ 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);