Browse Source

Firmware: ST0010 support + peripheral enable switches

ikari 13 years ago
parent
commit
1183718234
13 changed files with 125 additions and 40 deletions
  1. 11 3
      src/cli.c
  2. 1 1
      src/config
  3. 4 0
      src/fileops.c
  4. 1 0
      src/fileops.h
  5. 21 0
      src/fpga_spi.c
  6. 7 0
      src/fpga_spi.h
  7. 2 4
      src/main.c
  8. 32 6
      src/memory.c
  9. 1 1
      src/memory.h
  10. 22 14
      src/msu1.c
  11. 2 1
      src/msu1.h
  12. 16 9
      src/smc.c
  13. 5 1
      src/smc.h

+ 11 - 3
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 - 1
src/config

@@ -1,3 +1,3 @@
 CONFIG_VERSION=0.0.1
-CONFIG_FWVER=16777215
+CONFIG_FWVER=16777214
 CONFIG_MCU_FOSC=12000000

+ 4 - 0
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);

+ 1 - 0
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);

+ 21 - 0
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();
+}
+

+ 7 - 0
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

+ 2 - 4
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;
     }

+ 32 - 6
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) {

+ 1 - 1
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);

+ 22 - 14
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;

+ 2 - 1
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

+ 16 - 9
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;
 

+ 5 - 1
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;