From 11837182341a57d3f47ed2ad4eac0342c4c15278 Mon Sep 17 00:00:00 2001 From: ikari Date: Mon, 20 Jun 2011 14:22:52 +0200 Subject: [PATCH] Firmware: ST0010 support + peripheral enable switches --- src/cli.c | 14 +++++++++++--- src/config | 2 +- src/fileops.c | 4 ++++ src/fileops.h | 1 + src/fpga_spi.c | 21 +++++++++++++++++++++ src/fpga_spi.h | 7 +++++++ src/main.c | 6 ++---- src/memory.c | 38 ++++++++++++++++++++++++++++++++------ src/memory.h | 2 +- src/msu1.c | 36 ++++++++++++++++++++++-------------- src/msu1.h | 3 ++- src/smc.c | 25 ++++++++++++++++--------- src/smc.h | 6 +++++- 13 files changed, 125 insertions(+), 40 deletions(-) diff --git a/src/cli.c b/src/cli.c index bab76e6..4a80246 100644 --- a/src/cli.c +++ b/src/cli.c @@ -58,8 +58,8 @@ static char *curchar; /* Word lists */ static char command_words[] = - "cd\0reset\0sreset\0dir\0ls\0test\0resume\0loadrom\0loadraw\0saveraw\0put\0d4\0vmode\0mapper\0settime\0time\0"; -enum { CMD_CD = 0, CMD_RESET, CMD_SRESET, CMD_DIR, CMD_LS, CMD_TEST, CMD_RESUME, CMD_LOADROM, CMD_LOADRAW, CMD_SAVERAW, CMD_PUT, CMD_D4, CMD_VMODE, CMD_MAPPER, CMD_SETTIME, CMD_TIME }; + "cd\0reset\0sreset\0dir\0ls\0test\0resume\0loadrom\0loadraw\0saveraw\0put\0d4\0vmode\0mapper\0settime\0time\0setfeature\0"; +enum { CMD_CD = 0, CMD_RESET, CMD_SRESET, CMD_DIR, CMD_LS, CMD_TEST, CMD_RESUME, CMD_LOADROM, CMD_LOADRAW, CMD_SAVERAW, CMD_PUT, CMD_D4, CMD_VMODE, CMD_MAPPER, CMD_SETTIME, CMD_TIME, CMD_SETFEATURE }; /* ------------------------------------------------------------------------- */ /* Parse functions */ @@ -386,6 +386,11 @@ void cmd_time(void) { time.tm_mday, time.tm_hour, time.tm_min, time.tm_sec); } +void cmd_setfeature(void) { + uint8_t feat = parse_unsigned(0, 255); + fpga_set_features(feat); +} + /* ------------------------------------------------------------------------- */ /* CLI interface functions */ /* ------------------------------------------------------------------------- */ @@ -507,7 +512,10 @@ void cli_loop(void) { case CMD_TEST: testbattery(); break; + + case CMD_SETFEATURE: + cmd_setfeature(); + break; } - } } diff --git a/src/config b/src/config index 9e27807..32d7be7 100644 --- a/src/config +++ b/src/config @@ -1,3 +1,3 @@ CONFIG_VERSION=0.0.1 -CONFIG_FWVER=16777215 +CONFIG_FWVER=16777214 CONFIG_MCU_FOSC=12000000 diff --git a/src/fileops.c b/src/fileops.c index 3dd6d10..f211992 100644 --- a/src/fileops.c +++ b/src/fileops.c @@ -66,6 +66,10 @@ void file_close() { file_res = f_close(&file_handle); } +void file_seek(uint32_t offset) { + file_res = f_lseek(&file_handle, (DWORD)offset); +} + UINT file_read() { UINT bytes_read; file_res = f_read(&file_handle, file_buf, sizeof(file_buf), &bytes_read); diff --git a/src/fileops.h b/src/fileops.h index 8f55a70..b866b65 100644 --- a/src/fileops.h +++ b/src/fileops.h @@ -43,6 +43,7 @@ void file_init(void); void file_open(uint8_t* filename, BYTE flags); void file_open_by_filinfo(FILINFO* fno); void file_close(void); +void file_seek(uint32_t offset); UINT file_read(void); UINT file_write(void); UINT file_readblock(void* buf, uint32_t addr, uint16_t size); diff --git a/src/fpga_spi.c b/src/fpga_spi.c index 210de95..ab38f15 100644 --- a/src/fpga_spi.c +++ b/src/fpga_spi.c @@ -79,6 +79,7 @@ EA hhllxxxx write+incr. DSP data ROM (xxxx=dummy writes) EB - put DSP into reset EC - release DSP from reset + ED - set feature enable bits (see below) F0 - receive test token (to see if FPGA is alive) F1 - receive status (16bit, MSB first), see below @@ -110,6 +111,17 @@ 1 MSU1 Audio control status: 0=pause, 1=play 0 MSU1 Audio control request + FPGA feature enable bits: + bit function + ========================================================================== + 7 - + 6 - + 5 - + 4 - + 3 enable MSU1 registers + 2 enable SRTC registers + 1 enable ST0010 mapping + 0 enable DSPx mapping */ @@ -386,3 +398,12 @@ void fpga_dspx_reset(uint8_t reset) { FPGA_TX_BYTE(0x00); FPGA_DESELECT(); } + +void fpga_set_features(uint8_t feat) { + printf("set features: %02x\n", feat); + FPGA_SELECT(); + FPGA_TX_BYTE(0xed); + FPGA_TX_BYTE(feat); + FPGA_DESELECT(); +} + diff --git a/src/fpga_spi.h b/src/fpga_spi.h index fc06d5b..fc4778f 100644 --- a/src/fpga_spi.h +++ b/src/fpga_spi.h @@ -48,6 +48,12 @@ #define FPGA_SPI_FAST() spi_set_speed(SPI_SPEED_FPGA_FAST) #define FPGA_SPI_SLOW() spi_set_speed(SPI_SPEED_FPGA_SLOW) +#define FEAT_MSU1 (1 << 3) +#define FEAT_SRTC (1 << 2) +#define FEAT_ST0010 (1 << 1) +#define FEAT_DSPX (1 << 0) + + void fpga_spi_init(void); uint8_t fpga_test(void); uint16_t fpga_status(void); @@ -79,4 +85,5 @@ void fpga_reset_dspx_addr(void); void fpga_write_dspx_pgm(uint32_t data); void fpga_write_dspx_dat(uint16_t data); void fpga_dspx_reset(uint8_t reset); +void fpga_set_features(uint8_t feat); #endif diff --git a/src/main.c b/src/main.c index c1e750b..fd3e5d4 100644 --- a/src/main.c +++ b/src/main.c @@ -78,7 +78,7 @@ led_pwm(); printf("PCONP=%lx\n", LPC_SC->PCONP); file_init(); - cic_init(0); + cic_init(1); /* setup timer (fpga clk) */ LPC_TIM3->CTCR=0; LPC_TIM3->EMR=EMC0TOGGLE; @@ -237,7 +237,6 @@ sram_hexdump(SRAM_DIR_ADDR, 0x300); while(!cmd) { cmd=menu_main_loop(); printf("cmd: %d\n", cmd); - sleep_ms(500); uart_putc('-'); switch(cmd) { case SNES_CMD_LOADROM: @@ -262,8 +261,7 @@ sram_hexdump(SRAM_DIR_ADDR, 0x300); } printf("cmd was %x, going to snes main loop\n", cmd); - /* always try MSU1 for now */ - if(msu1_entrycheck_and_loop()) { + if(romprops.has_msu1 && msu1_loop()) { prepare_reset(); continue; } diff --git a/src/memory.c b/src/memory.c index a308161..25c67a5 100644 --- a/src/memory.c +++ b/src/memory.c @@ -42,6 +42,7 @@ #include "rle.h" #include "diskio.h" #include "snesboot.h" +#include "msu1.h" #include char* hex = "0123456789ABCDEF"; @@ -181,7 +182,6 @@ uint32_t load_rom(uint8_t* filename, uint32_t base_addr, uint8_t flags) { filesize = file_handle.fsize; smc_id(&romprops); set_mcu_addr(base_addr); - printf("no nervous breakdown beyond this point! or else!\n"); f_lseek(&file_handle, romprops.offset); for(;;) { ff_sd_offload=1; @@ -218,9 +218,13 @@ uint32_t load_rom(uint8_t* filename, uint32_t base_addr, uint8_t flags) { } if(romprops.has_dspx) { printf("DSPx game. Loading firmware image %s...\n", romprops.necdsp_fw); - load_dspx(romprops.necdsp_fw); - if(file_res && romprops.necdsp_fw == DSPFW_1) { - load_dspx(DSPFW_1B); + if(romprops.has_st0010) { + load_dspx(romprops.necdsp_fw, 1); + } else { + load_dspx(romprops.necdsp_fw, 0); + if(file_res && romprops.necdsp_fw == DSPFW_1) { + load_dspx(DSPFW_1B, 0); + } } if(file_res) { snes_menu_errmsg(MENU_ERR_NODSP, (void*)romprops.necdsp_fw); @@ -253,6 +257,17 @@ uint32_t load_rom(uint8_t* filename, uint32_t base_addr, uint8_t flags) { } } + printf("check MSU..."); + if(msu1_check(filename)) { + romprops.fpga_features |= FEAT_MSU1; + romprops.has_msu1 = 1; + } + printf("done\n"); + + romprops.fpga_features |= FEAT_SRTC; + + fpga_set_features(romprops.fpga_features); + if(flags & LOADROM_WITH_RESET) { set_mcu_ovr(0); fpga_dspx_reset(1); @@ -465,7 +480,7 @@ uint64_t sram_gettime(uint32_t base_addr) { return result & 0x00ffffffffffffffLL; } -void load_dspx(const uint8_t *filename) { +void load_dspx(const uint8_t *filename, uint8_t st0010) { UINT bytes_read; DWORD filesize; uint16_t word_cnt; @@ -473,9 +488,16 @@ void load_dspx(const uint8_t *filename) { uint16_t sector_remaining = 0; uint16_t sector_cnt = 0; uint16_t pgmsize = 2048; - uint16_t datsize = 1024; + uint16_t datsize; uint32_t pgmdata = 0; uint16_t datdata = 0; + + if(st0010) { + datsize = 1536; + } else { + datsize = 1024; + } + file_open((uint8_t*)filename, FA_READ); filesize = file_handle.fsize; if(file_res) { @@ -503,6 +525,10 @@ void load_dspx(const uint8_t *filename) { } wordsize_cnt = 0; + if(st0010) { + file_seek(0xc000); + sector_remaining = 0; + } for(word_cnt = 0; word_cnt < datsize;) { if(!sector_remaining) { diff --git a/src/memory.h b/src/memory.h index 7bb1347..c2018f4 100644 --- a/src/memory.h +++ b/src/memory.h @@ -52,7 +52,7 @@ uint32_t load_sram(uint8_t* filename, uint32_t base_addr); uint32_t load_sram_offload(uint8_t* filename, uint32_t base_addr); uint32_t load_sram_rle(uint8_t* filename, uint32_t base_addr); uint32_t load_bootrle(uint32_t base_addr); -void load_dspx(const uint8_t* filename); +void load_dspx(const uint8_t* filename, uint8_t st0010); void sram_hexdump(uint32_t addr, uint32_t len); uint8_t sram_readbyte(uint32_t addr); uint16_t sram_readshort(uint32_t addr); diff --git a/src/msu1.c b/src/msu1.c index 87e6dbb..179810c 100644 --- a/src/msu1.c +++ b/src/msu1.c @@ -10,6 +10,10 @@ #include "msu1.h" #include "snes.h" #include "timer.h" +#include "smc.h" + +FIL msufile; +extern snes_romprops_t romprops; int msu1_check_reset(void) { static tick_t rising_ticks; @@ -27,17 +31,21 @@ int msu1_check_reset(void) { return 0; } -int msu1_entrycheck_and_loop() { -/* MSU1 STUFF, GET ME OUTTA HERE */ - FIL durr; -// open MSU file - strcpy((char*)file_buf, (char*)file_lfn); +int msu1_check(uint8_t* filename) { +/* open MSU file */ + strcpy((char*)file_buf, (char*)filename); strcpy(strrchr((char*)file_buf, (int)'.'), ".msu"); printf("MSU datafile: %s\n", file_buf); - if(f_open(&durr, (const TCHAR*)file_buf, FA_READ) != FR_OK) { + if(f_open(&msufile, (const TCHAR*)file_buf, FA_READ) != FR_OK) { printf("MSU datafile not found\n"); return 0; } + romprops.fpga_features |= FEAT_MSU1; + return 1; +} + +int msu1_loop() { +/* it is assumed that the MSU file is already opened by calling msu1_check(). */ UINT bytes_read = 1024; UINT bytes_read2 = 1; FRESULT res; @@ -61,10 +69,10 @@ int msu1_entrycheck_and_loop() { msu_reset(0x0); ff_sd_offload=1; sd_offload_tgt=2; - f_lseek(&durr, 0L); + f_lseek(&msufile, 0L); ff_sd_offload=1; sd_offload_tgt=2; - f_read(&durr, file_buf, 16384, &bytes_read2); + f_read(&msufile, file_buf, 16384, &bytes_read2); set_dac_addr(dac_addr); dac_pause(); @@ -90,7 +98,7 @@ int msu1_entrycheck_and_loop() { set_msu_addr(msu_addr); sd_offload_tgt=2; ff_sd_offload=1; - res = f_read(&durr, file_buf, 8192, &bytes_read2); + res = f_read(&msufile, file_buf, 8192, &bytes_read2); DBG_MSU1 printf("data buffer refilled. res=%d page1=%08lx page2=%08lx\n", res, msu_page1_start, msu_page2_start); } @@ -153,12 +161,12 @@ int msu1_entrycheck_and_loop() { set_msu_addr(0x0); sd_offload_tgt=2; ff_sd_offload=1; - res = f_lseek(&durr, msu_offset); + res = f_lseek(&msufile, msu_offset); DBG_MSU1 printf("seek to %08lx, res = %d\n", msu_offset, res); sd_offload_tgt=2; ff_sd_offload=1; - res = f_read(&durr, file_buf, 16384, &bytes_read2); + res = f_read(&msufile, file_buf, 16384, &bytes_read2); DBG_MSU1 printf("read res = %d\n", res); DBG_MSU1 printf("read %d bytes\n", bytes_read2); msu_reset(0x0); @@ -172,7 +180,7 @@ int msu1_entrycheck_and_loop() { set_msu_addr(0x2000); sd_offload_tgt=2; ff_sd_offload=1; - f_read(&durr, file_buf, 8192, &bytes_read2); + f_read(&msufile, file_buf, 8192, &bytes_read2); DBG_MSU1 printf("next page dirty (was: %08lx), loaded page2 (start now: ", msu_page2_start); msu_page2_start = msu_page1_start + msu_page_size; DBG_MSU1 printf("%08lx)\n", msu_page2_start); @@ -184,7 +192,7 @@ int msu1_entrycheck_and_loop() { set_msu_addr(0x0); sd_offload_tgt=2; ff_sd_offload=1; - f_read(&durr, file_buf, 8192, &bytes_read2); + f_read(&msufile, file_buf, 8192, &bytes_read2); DBG_MSU1 printf("next page dirty (was: %08lx), loaded page1 (start now: ", msu_page1_start); msu_page1_start = msu_page2_start + msu_page_size; DBG_MSU1 printf("%08lx)\n", msu_page1_start); @@ -240,7 +248,7 @@ int msu1_entrycheck_and_loop() { bytes_read = MSU_DAC_BUFSIZE; } if(msu1_check_reset()) { - f_close(&durr); + f_close(&msufile); f_close(&file_handle); spi_set_speed(SSP_CLK_DIVISOR_FPGA_SLOW); return 1; diff --git a/src/msu1.h b/src/msu1.h index 6646e2c..1407a32 100644 --- a/src/msu1.h +++ b/src/msu1.h @@ -9,6 +9,7 @@ #define MSU_DAC_BUFSIZE (2048) -int msu1_entrycheck_and_loop(void); +int msu1_check(uint8_t*); +int msu1_loop(void); #endif diff --git a/src/smc.c b/src/smc.c index ed86a71..0cf17b6 100644 --- a/src/smc.c +++ b/src/smc.c @@ -29,6 +29,7 @@ #include "uart.h" #include "smc.h" #include "string.h" +#include "fpga_spi.h" snes_romprops_t romprops; @@ -81,6 +82,8 @@ void smc_id(snes_romprops_t* props) { snes_header_t* header = &(props->header); props->has_dspx = 0; + props->has_st0010 = 0; + props->fpga_features = 0; for(uint8_t num = 0; num < 6; num++) { if(!file_readblock(header, hdr_addr[num], sizeof(snes_header_t)) || file_res) { @@ -138,20 +141,20 @@ void smc_id(snes_romprops_t* props) { switch(header->map & 0xef) { case 0x21: /* HiROM */ + props->mapper_id = 0; if(header->map == 0x31 && (header->carttype == 0x03 || header->carttype == 0x05)) { props->has_dspx = 1; - props->mapper_id = 4; /* DSPx HiROM */ props->necdsp_fw = DSPFW_1B; - } else { - props->mapper_id = 0; /* regular HiROM */ + props->fpga_features |= FEAT_DSPX; } break; case 0x20: /* LoROM */ + props->mapper_id = 1; if ((header->map == 0x20 && header->carttype == 0x03) || (header->map == 0x30 && header->carttype == 0x05 && header->licensee != 0xb2)) { - props->mapper_id = 5; props->has_dspx = 1; + props->fpga_features |= FEAT_DSPX; // Pilotwings uses DSP1 instead of DSP1B if(!memcmp(header->name, "PILOTWINGS", 10)) { props->necdsp_fw = DSPFW_1; @@ -160,18 +163,22 @@ void smc_id(snes_romprops_t* props) { } } else if (header->map == 0x20 && header->carttype == 0x05) { props->has_dspx = 1; - props->mapper_id = 5; /* DSPx LoROM */ props->necdsp_fw = DSPFW_2; + props->fpga_features |= FEAT_DSPX; } else if (header->map == 0x30 && header->carttype == 0x05 && header->licensee == 0xb2) { props->has_dspx = 1; - props->mapper_id = 5; /* DSPx LoROM */ props->necdsp_fw = DSPFW_3; + props->fpga_features |= FEAT_DSPX; } else if (header->map == 0x30 && header->carttype == 0x03) { props->has_dspx = 1; - props->mapper_id = 5; /* DSPx LoROM */ props->necdsp_fw = DSPFW_4; - } else { - props->mapper_id = 1; /* regular LoROM */ + props->fpga_features |= FEAT_DSPX; + } else if (header->map == 0x30 && header->carttype == 0xf6 && header->romsize >= 0xa) { + props->has_dspx = 1; + props->has_st0010 = 1; + props->necdsp_fw = DSPFW_ST0010; + props->fpga_features |= FEAT_ST0010; + header->ramsize = 2; } break; diff --git a/src/smc.h b/src/smc.h index 271122b..54062fe 100644 --- a/src/smc.h +++ b/src/smc.h @@ -31,7 +31,8 @@ #define DSPFW_2 ((const uint8_t*)"/sd2snes/dsp2.bin") #define DSPFW_3 ((const uint8_t*)"/sd2snes/dsp3.bin") #define DSPFW_4 ((const uint8_t*)"/sd2snes/dsp4.bin") -#define DSPFW_1B ((const uint8_t*)"/sd2snes/dsp1b.bin") +#define DSPFW_1B ((const uint8_t*)"/sd2snes/dsp1b.bin") +#define DSPFW_ST0010 ((const uint8_t*)"/sd2snes/st0010.bin") typedef struct _snes_header { uint8_t maker[2]; /* 0xB0 */ @@ -61,6 +62,9 @@ typedef struct _snes_romprops { uint32_t romsize_bytes; /* ROM size in bytes (rounded up) */ const uint8_t* necdsp_fw; /* NEC DSP ROM filename */ uint8_t has_dspx; /* DSP[1-4] presence flag */ + uint8_t has_st0010; /* st0010 presence flag (additional to dspx)*/ + uint8_t has_msu1; /* MSU1 presence flag */ + uint8_t fpga_features; /* feature/peripheral enable bits*/ snes_header_t header; /* original header from ROM image */ } snes_romprops_t;