Firmware: ST0010 support + peripheral enable switches
This commit is contained in:
parent
7fc6952fab
commit
1183718234
14
src/cli.c
14
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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
CONFIG_VERSION=0.0.1
|
||||
CONFIG_FWVER=16777215
|
||||
CONFIG_FWVER=16777214
|
||||
CONFIG_MCU_FOSC=12000000
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
38
src/memory.c
38
src/memory.c
@ -42,6 +42,7 @@
|
||||
#include "rle.h"
|
||||
#include "diskio.h"
|
||||
#include "snesboot.h"
|
||||
#include "msu1.h"
|
||||
|
||||
#include <string.h>
|
||||
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) {
|
||||
|
||||
@ -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);
|
||||
|
||||
36
src/msu1.c
36
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;
|
||||
|
||||
@ -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
|
||||
|
||||
25
src/smc.c
25
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;
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user