Parcourir la source

Firmware: uPD77c25 program download, reset

ikari il y a 13 ans
Parent
commit
344fa362be
14 fichiers modifiés avec 176 ajouts et 15 suppressions
  1. 2 0
      src/bootldr/config.h
  2. 2 1
      src/bootldr/iap.c
  3. 3 1
      src/bootldr/main.c
  4. 1 1
      src/flash.script
  5. 41 0
      src/fpga_spi.c
  6. 4 1
      src/fpga_spi.h
  7. 2 0
      src/led.c
  8. 1 1
      src/lpc1754.ld
  9. 7 4
      src/main.c
  10. 68 0
      src/memory.c
  11. 1 0
      src/memory.h
  12. 41 5
      src/smc.c
  13. 2 1
      src/smc.h
  14. 1 0
      src/snes.c

+ 2 - 0
src/bootldr/config.h

@@ -5,6 +5,8 @@
 // #define DEBUG_IRQ
 // #define DEBUG_MSU1
 
+// #define DEBUG_UART
+
 #ifdef DEBUG_UART
 #define DBG_UART
 #else

+ 2 - 1
src/bootldr/iap.c

@@ -151,6 +151,7 @@ FLASH_RES flash_file(uint8_t *filename) {
 
     uint32_t res;
 
+    writeled(1);
     DBG_BL printf("erasing flash...\n");
     if((res = iap_prepare_for_write(FW_START / 0x1000, FLASH_SECTORS)) != CMD_SUCCESS) {
       DBG_BL printf("error %ld while preparing for erase\n", res);
@@ -172,7 +173,6 @@ FLASH_RES flash_file(uint8_t *filename) {
                                          : (flash_addr >> 12);
       DBG_BL printf("current_sec=%d flash_addr=%08lx\n", current_sec, flash_addr);
       DBG_UART uart_putc('.');
-      toggle_rdy_led();
       if(current_sec < (FW_START / 0x1000)) return ERR_FLASH;
       if((res = iap_prepare_for_write(current_sec, current_sec)) != CMD_SUCCESS) {
         DBG_BL printf("error %ld while preparing sector %d for write\n", res, current_sec);
@@ -188,6 +188,7 @@ FLASH_RES flash_file(uint8_t *filename) {
       DBG_UART uart_putc('X');
       return ERR_FILECHK;
     }
+    writeled(0);
   } else {
     DBG_UART uart_putc('n');
     DBG_BL printf("flash content is ok, no version mismatch, no forced upgrade. No need to flash\n");

+ 3 - 1
src/bootldr/main.c

@@ -45,7 +45,7 @@ int main(void) {
   DBG_UART uart_init();
   led_init();
   readled(0);
-  rdyled(0);
+  rdyled(1);
   writeled(0);
  /* do this last because the peripheral init()s change PCLK dividers */
   clock_init();
@@ -63,9 +63,11 @@ DBG_BL printf("PCONP=%lx\n", LPC_SC->PCONP);
 
   FLASH_RES res = flash_file((uint8_t*)"/sd2snes/firmware.img");
   if(res == ERR_FLASHPREP || res == ERR_FLASHERASE || res == ERR_FLASH) {
+    rdyled(0);
     writeled(1);
   }
   if(res == ERR_FILEHD || res == ERR_FILECHK) {
+    rdyled(0);
     readled(1);
   }
   DBG_BL printf("flash result = %d\n", res);

+ 1 - 1
src/flash.script

@@ -6,7 +6,7 @@
 #flash info 0
 
 reset init
-flash write_image erase unlock obj/firmware.img 8192
+flash write_image erase unlock obj/firmware.img 12288
 reset run
 shutdown
 

+ 41 - 0
src/fpga_spi.c

@@ -74,6 +74,11 @@
                                 eg 0x20111210094816 is 2011-12-10, 9:48:16
 	E6	ssrr		set/reset BS-X status register [7:0]
 	E7	-		reset SRTC state
+	E8	-		reset DSP program and data ROM write pointers
+	E9	hhmmllxxxx	write+incr. DSP program ROM (xxxx=dummy writes)
+	EA	hhllxxxx	write+incr. DSP data ROM (xxxx=dummy writes)
+	EB	-		put DSP into reset
+	EC	-		release DSP from reset
 	F0	-		receive test token (to see if FPGA is alive)
 	F1	-		receive status (16bit, MSB first), see below
 
@@ -345,3 +350,39 @@ void fpga_reset_srtc_state() {
   FPGA_TX_BYTE(0x00);
   FPGA_DESELECT();
 }
+
+void fpga_reset_dspx_addr() {
+  FPGA_SELECT();
+  FPGA_TX_BYTE(0xe8);
+  FPGA_TX_BYTE(0x00);
+  FPGA_TX_BYTE(0x00);
+  FPGA_DESELECT();
+}
+
+void fpga_write_dspx_pgm(uint32_t data) {
+  FPGA_SELECT();
+  FPGA_TX_BYTE(0xe9);
+  FPGA_TX_BYTE((data>>16)&0xff);
+  FPGA_TX_BYTE((data>>8)&0xff);
+  FPGA_TX_BYTE((data)&0xff);
+  FPGA_TX_BYTE(0x00);
+  FPGA_TX_BYTE(0x00);
+  FPGA_DESELECT();
+}
+
+void fpga_write_dspx_dat(uint16_t data) {
+  FPGA_SELECT();
+  FPGA_TX_BYTE(0xea);
+  FPGA_TX_BYTE((data>>8)&0xff);
+  FPGA_TX_BYTE((data)&0xff);
+  FPGA_TX_BYTE(0x00);
+  FPGA_TX_BYTE(0x00);
+  FPGA_DESELECT();
+}
+
+void fpga_dspx_reset(uint8_t reset) {
+  FPGA_SELECT();
+  FPGA_TX_BYTE(reset ? 0xeb : 0xec);
+  FPGA_TX_BYTE(0x00);
+  FPGA_DESELECT();
+}

+ 4 - 1
src/fpga_spi.h

@@ -75,5 +75,8 @@ uint32_t get_snes_sysclk(void);
 void set_bsx_regs(uint8_t set, uint8_t reset);
 void set_fpga_time(uint64_t time);
 void fpga_reset_srtc_state(void);
-
+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);
 #endif

+ 2 - 0
src/led.c

@@ -4,6 +4,7 @@
 #include "bits.h"
 #include "timer.h"
 #include "led.h"
+#include "cli.h"
 
 static uint8_t led_bright[16]={255,253,252,251,249,247,244,239,232,223,210,191,165,127,74,0};
 
@@ -92,6 +93,7 @@ void led_panic() {
     LPC_GPIO2->FIODIR &= ~(BV(4) | BV(5));
     LPC_GPIO1->FIODIR &= ~BV(23);
     delay_ms(350);
+    cli_entrycheck();
   }
 }
 

+ 1 - 1
src/lpc1754.ld

@@ -10,7 +10,7 @@ ENTRY(_start)
 
 MEMORY
 {
-  flash  (rx)  : ORIGIN = 0x00002100, LENGTH = 0x1df00 /* leave room for bootldr + metadata */
+  flash  (rx)  : ORIGIN = 0x00003100, LENGTH = 0x1cf00 /* leave room for bootldr + metadata */
   ram    (rwx) : ORIGIN = 0x10000000, LENGTH = 0x04000
   ahbram (rwx) : ORIGIN = 0x2007C000, LENGTH = 0x04000
 }

+ 7 - 4
src/main.c

@@ -131,7 +131,7 @@ printf("PCONP=%lx\n", LPC_SC->PCONP);
     snes_bootprint("           Loading ...          \0");
     if(get_cic_state() == CIC_PAIR) {
       printf("PAIR MODE ENGAGED!\n");
-      cic_pair(CIC_PAL, CIC_NTSC);
+      cic_pair(CIC_NTSC, CIC_NTSC);
     }
     rdyled(1);
     readled(0);
@@ -189,6 +189,7 @@ printf("PCONP=%lx\n", LPC_SC->PCONP);
     /* load menu */
 
     fpga_pgm((uint8_t*)"/sd2snes/fpga_base.bit");
+    fpga_dspx_reset(1);
     uart_putc('(');
     load_rom((uint8_t*)"/sd2snes/menu.bin", SRAM_MENU_ADDR);
     /* force memory size + mapper */
@@ -224,7 +225,7 @@ printf("PCONP=%lx\n", LPC_SC->PCONP);
     uint32_t filesize=0;
     sram_writebyte(32, SRAM_CMD_ADDR);
     printf("test sram\n");
-    while(!sram_reliable());
+    while(!sram_reliable()) cli_entrycheck();
     printf("ok\n");
 sram_hexdump(SRAM_DIR_ADDR, 0x300);
 //while(1) {
@@ -237,13 +238,14 @@ sram_hexdump(SRAM_DIR_ADDR, 0x300);
       cmd=menu_main_loop();
 // cmd = 1;
       printf("cmd: %d\n", cmd);
-      sleep_ms(50);
+      sleep_ms(500);
       uart_putc('-');
       switch(cmd) {
 	case SNES_CMD_LOADROM:
 	  get_selected_name(file_lfn);
 	  set_mcu_ovr(1);
-// strcpy((char*)file_lfn, "/bs3-1.smc");
+// strcpy((char*)file_lfn, "/mon.smc");
+
 	  printf("Selected name: %s\n", file_lfn);
 	  filesize = load_rom(file_lfn, SRAM_ROM_ADDR);
 	  if(romprops.ramsize_bytes) {
@@ -257,6 +259,7 @@ sram_hexdump(SRAM_DIR_ADDR, 0x300);
 	  snes_reset(1);
 	  delay_ms(10);
 	  snes_reset(0);
+          fpga_dspx_reset(0);
 	  break;
 	case SNES_CMD_SETRTC:
           /* get time from RAM */

+ 68 - 0
src/memory.c

@@ -229,6 +229,10 @@ ticks_total=getticks()-ticksstart;
     sram_writebyte(0xfc, rombase+0xd5);
     set_fpga_time(0x0220110301180530LL);
   }
+  if(romprops.mapper_id == 4 || romprops.mapper_id == 5) {
+    printf("DSPx game. Loading firmware image %s...\n", romprops.necdsp_fw);
+    load_dspx(romprops.necdsp_fw);
+  }
   uint32_t rammask;
   uint32_t rommask;
 
@@ -448,3 +452,67 @@ uint64_t sram_gettime(uint32_t base_addr) {
   FPGA_DESELECT();
   return result & 0x00ffffffffffffffLL;
 }
+
+void load_dspx(const uint8_t *filename) {
+  UINT bytes_read;
+  DWORD filesize;
+  uint16_t word_cnt;
+  uint8_t wordsize_cnt = 0;
+  uint16_t sector_remaining = 0;
+  uint16_t sector_cnt = 0;
+  uint16_t pgmsize = 2048;
+  uint16_t datsize = 1024;
+  uint32_t pgmdata = 0;
+  uint16_t datdata = 0;
+  file_open((uint8_t*)filename, FA_READ);
+  filesize = file_handle.fsize;
+  if(file_res) {
+    printf("Could not read %s: error %d\n", filename, file_res);
+    return;
+  }
+
+  fpga_reset_dspx_addr();
+
+  for(word_cnt = 0; word_cnt < pgmsize;) {
+    if(!sector_remaining) {
+      bytes_read = file_read();
+      sector_remaining = bytes_read;
+      sector_cnt = 0;
+    }
+    pgmdata = (pgmdata << 8) | file_buf[sector_cnt];
+    sector_cnt++;
+    wordsize_cnt++;
+    sector_remaining--;
+    if(wordsize_cnt == 3){
+      wordsize_cnt = 0;
+      word_cnt++;
+      fpga_write_dspx_pgm(pgmdata);
+      printf("%06lx ", pgmdata&0xffffff);
+    }
+  }
+
+  wordsize_cnt = 0;
+
+  for(word_cnt = 0; word_cnt < datsize;) {
+    if(!sector_remaining) {
+      bytes_read = file_read();
+      sector_remaining = bytes_read;
+      sector_cnt = 0;
+    }
+    datdata = (datdata << 8) | file_buf[sector_cnt];
+    sector_cnt++;
+    wordsize_cnt++;
+    sector_remaining--;
+    if(wordsize_cnt == 2){
+      wordsize_cnt = 0;
+      word_cnt++;
+      fpga_write_dspx_dat(datdata);
+      printf("%04x ",datdata&0xffff);
+    }
+  }
+
+  fpga_reset_dspx_addr();
+
+  file_close();
+
+}

+ 1 - 0
src/memory.h

@@ -49,6 +49,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 sram_hexdump(uint32_t addr, uint32_t len);
 uint8_t sram_readbyte(uint32_t addr);
 uint16_t sram_readshort(uint32_t addr);

+ 41 - 5
src/smc.c

@@ -28,9 +28,16 @@
 #include "config.h"
 #include "uart.h"
 #include "smc.h"
+#include "string.h"
 
 snes_romprops_t romprops;
 
+const uint8_t* DSPFW_1  = (uint8_t*)"/sd2snes/dsp1.bin";
+const uint8_t* DSPFW_1B = (uint8_t*)"/sd2snes/dsp1b.bin";
+const uint8_t* DSPFW_2  = (uint8_t*)"/sd2snes/dsp2.bin";
+const uint8_t* DSPFW_3  = (uint8_t*)"/sd2snes/dsp3.bin";
+const uint8_t* DSPFW_4  = (uint8_t*)"/sd2snes/dsp4.bin";
+
 uint32_t hdr_addr[6] = {0xffb0, 0x101b0, 0x7fb0, 0x81b0, 0x40ffb0, 0x4101b0};
 uint8_t countAllASCII(uint8_t* data, int size) {
   uint8_t res = 0;
@@ -77,7 +84,6 @@ uint8_t checkChksum(uint16_t cchk, uint16_t chk) {
 
 void smc_id(snes_romprops_t* props) {
   uint8_t score, maxscore=1, score_idx=2; /* assume LoROM */
-
   snes_header_t* header = &(props->header);
 
   for(uint8_t num = 0; num < 6; num++) {
@@ -122,7 +128,7 @@ void smc_id(snes_romprops_t* props) {
       const uint8_t n15 = header->map;
       if(n15 == 0x00 || n15 == 0x80 || n15 == 0x84 || n15 == 0x9c
         || n15 == 0xbc || n15 == 0xfc) {
-        if(header->fixed_33 == 0x33 || header->fixed_33 == 0xff) {
+        if(header->licensee == 0x33 || header->licensee == 0xff) {
           props->mapper_id = 0;
 /*XXX do this properly */
           props->ramsize_bytes = 0x8000;
@@ -135,15 +141,44 @@ 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->mapper_id = 4; /* DSPx HiROM */
+        props->necdsp_fw = DSPFW_1B;
+      } else {
+        props->mapper_id = 0; /* regular HiROM */
+      }
       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;
+        // Pilotwings uses DSP1 instead of DSP1B
+        if(!memcmp(header->name, "PILOTWINGS", 10)) {
+          props->necdsp_fw = DSPFW_1;
+        } else {
+          props->necdsp_fw = DSPFW_1B;
+        }
+      } else if (header->map == 0x20 && header->carttype == 0x05) {
+        props->mapper_id = 5; /* DSPx LoROM */
+        props->necdsp_fw = DSPFW_2;
+      } else if (header->map == 0x30 && header->carttype == 0x05 && header->licensee == 0xb2) {
+        props->mapper_id = 5; /* DSPx LoROM */
+        props->necdsp_fw = DSPFW_3;
+      } else if (header->map == 0x30 && header->carttype == 0x03) {
+        props->mapper_id = 5; /* DSPx LoROM */
+        props->necdsp_fw = DSPFW_4;
+      } else {
+        props->mapper_id = 1; /* regular LoROM */
+      }
       break;
+
     case 0x25: /* ExHiROM */
       props->mapper_id = 2;
       break;
+
     case 0x22: /* ExLoROM */
       if(file_handle.fsize > 0x400200) {
         props->mapper_id = 6; /* SO96 */
@@ -151,6 +186,7 @@ void smc_id(snes_romprops_t* props) {
         props->mapper_id = 4;
       }
       break;
+
     default: /* invalid/unsupported mapper, use header location */
       switch(score_idx) {
         case 0:
@@ -194,7 +230,7 @@ uint8_t smc_headerscore(snes_header_t* header) {
   score += countAllASCII(header->gamecode, sizeof(header->gamecode));
   score += isFixed(header->fixed_00, sizeof(header->fixed_00), 0x00);
   score += countAllJISX0201(header->name, sizeof(header->name));
-  score += 3*isFixed(&header->fixed_33, sizeof(header->fixed_33), 0x33);
+  score += 3*isFixed(&header->licensee, sizeof(header->licensee), 0x33);
   score += checkChksum(header->cchk, header->chk);
   return score;
 }

+ 2 - 1
src/smc.h

@@ -40,7 +40,7 @@ typedef struct _snes_header {
   uint8_t romsize;      /* 0xD7 */
   uint8_t ramsize;      /* 0xD8 */
   uint8_t destcode;     /* 0xD9 */
-  uint8_t fixed_33;     /* 0xDA */
+  uint8_t licensee;     /* 0xDA */
   uint8_t ver;          /* 0xDB */
   uint16_t cchk;        /* 0xDC */
   uint16_t chk;         /* 0xDE */
@@ -53,6 +53,7 @@ typedef struct _snes_romprops {
   uint32_t expramsize_bytes;  /* ExpRAM size in bytes */
   uint32_t ramsize_bytes;     /* CartRAM size in bytes */
   uint32_t romsize_bytes;     /* ROM size in bytes (rounded up) */
+  const uint8_t* necdsp_fw;   /* NEC DSP ROM filename */
   snes_header_t header;       /* original header from ROM image */
 } snes_romprops_t;
 

+ 1 - 0
src/snes.c

@@ -60,6 +60,7 @@ void prepare_reset() {
   snes_reset(0);
   while(get_snes_reset());
   snes_reset(1);
+  fpga_dspx_reset(1);
   delay_ms(200);
 }