main.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  1. /* sd2snes - SD card based universal cartridge for the SNES
  2. Copyright (C) 2009-2010 Maximilian Rehkopf <otakon@gmx.net>
  3. AVR firmware portion
  4. Inspired by and based on code from sd2iec, written by Ingo Korb et al.
  5. See sdcard.c|h, config.h.
  6. FAT file system access based on code by ChaN, Jim Brain, Ingo Korb,
  7. see ff.c|h.
  8. This program is free software; you can redistribute it and/or modify
  9. it under the terms of the GNU General Public License as published by
  10. the Free Software Foundation; version 2 of the License only.
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. GNU General Public License for more details.
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  18. main.c: initialization and flow
  19. */
  20. #include <stdio.h>
  21. #include <string.h>
  22. #include <avr/boot.h>
  23. #include <avr/interrupt.h>
  24. #include <avr/pgmspace.h>
  25. #include <avr/power.h>
  26. #include <avr/wdt.h>
  27. #include <util/delay.h>
  28. #include "config.h"
  29. #include "diskio.h"
  30. #include "ff.h"
  31. #include "led.h"
  32. /* #include "timer.h" */
  33. #include "fpga.h"
  34. #include "uart.h"
  35. #include "ustring.h"
  36. #include "utils.h"
  37. #include "snes.h"
  38. #include "fileops.h"
  39. #include "memory.h"
  40. #include "fpga_spi.h"
  41. #include "spi.h"
  42. #include "avrcompat.h"
  43. #include "filetypes.h"
  44. #include "sdcard.h"
  45. void writetest(void) {
  46. // HERE BE LIONS, GET IN THE CAR
  47. char teststring[58];
  48. while(1) {
  49. sram_writeblock((void*)"Testtext of DOOM!!1! 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ", SRAM_SCRATCHPAD+0x20, 58);
  50. sram_readblock((void*)teststring, SRAM_SCRATCHPAD+0x20, 58);
  51. teststring[57]=0;
  52. dprintf("%s\n", teststring);
  53. }
  54. // END OF LIONS
  55. }
  56. void memtest(void) {
  57. /* HERE BE DRAGONS */
  58. uint32_t dbg_i;
  59. for(dbg_i=0; dbg_i < 65536; dbg_i++) {
  60. sram_writeshort((uint16_t)dbg_i&0xffff, dbg_i*2);
  61. }
  62. save_sram((uint8_t*)"/sd2snes/memtest", 0x20000, 0);
  63. set_pwr_led(0);
  64. while(1);
  65. /* END OF DRAGONS */
  66. }
  67. /* Make sure the watchdog is disabled as soon as possible */
  68. /* Copy this code to your bootloader if you use one and your */
  69. /* MCU doesn't disable the WDT after reset! */
  70. void get_mcusr(void) \
  71. __attribute__((naked)) \
  72. __attribute__((section(".init3")));
  73. void get_mcusr(void)
  74. {
  75. MCUSR = 0;
  76. wdt_disable();
  77. }
  78. #ifdef CONFIG_MEMPOISON
  79. void poison_memory(void) \
  80. __attribute__((naked)) \
  81. __attribute__((section(".init1")));
  82. void poison_memory(void) {
  83. register uint16_t i;
  84. register uint8_t *ptr;
  85. asm("clr r1\n");
  86. /* There is no RAMSTARt variable =( */
  87. if (RAMEND > 2048 && RAMEND < 4096) {
  88. /* 2K memory */
  89. ptr = (void *)RAMEND-2047;
  90. for (i=0;i<2048;i++)
  91. ptr[i] = 0x55;
  92. } else if (RAMEND > 4096 && RAMEND < 8192) {
  93. /* 4K memory */
  94. ptr = (void *)RAMEND-4095;
  95. for (i=0;i<4096;i++)
  96. ptr[i] = 0x55;
  97. } else {
  98. /* Assume 8K memory */
  99. ptr = (void *)RAMEND-8191;
  100. for (i=0;i<8192;i++)
  101. ptr[i] = 0x55;
  102. }
  103. }
  104. #endif
  105. #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 1)
  106. int main(void) __attribute__((OS_main));
  107. #endif
  108. int main(void) {
  109. #if defined __AVR_ATmega644__ || defined __AVR_ATmega644P__ || defined __AVR_ATmega2561__
  110. asm volatile("in r24, %0\n"
  111. "ori r24, 0x80\n"
  112. "out %0, r24\n"
  113. "out %0, r24\n"
  114. :
  115. : "I" (_SFR_IO_ADDR(MCUCR))
  116. : "r24"
  117. );
  118. #elif defined __AVR_ATmega32__
  119. asm volatile ("in r24, %0\n"
  120. "ori r24, 0x80\n"
  121. "out %0, r24\n"
  122. "out %0, r24\n"
  123. :
  124. : "I" (_SFR_IO_ADDR(MCUCSR))
  125. : "r24"
  126. );
  127. #elif defined __AVR_ATmega128__ || defined __AVR_ATmega1281__
  128. /* Just assume that JTAG doesn't hurt us on the m128 */
  129. #else
  130. # error Unknown chip!
  131. #endif
  132. #ifdef CLOCK_PRESCALE
  133. clock_prescale_set(CLOCK_PRESCALE);
  134. #endif
  135. set_pwr_led(0);
  136. set_busy_led(1);
  137. spi_none();
  138. snes_reset(1);
  139. uart_init();
  140. sei();
  141. _delay_ms(100);
  142. disk_init();
  143. snes_init();
  144. /* timer_init(); */
  145. uart_puts_P(PSTR("\nsd2snes " VERSION));
  146. uart_putcrlf();
  147. file_init();
  148. FATFS fatfs;
  149. f_mount(0,&fatfs);
  150. uart_putc('W');
  151. fpga_init();
  152. fpga_pgm((uint8_t*)"/sd2snes/main.bit");
  153. _delay_ms(100);
  154. set_pwr_led(1);
  155. fpga_spi_init();
  156. uart_putc('!');
  157. _delay_ms(100);
  158. restart:
  159. set_avr_ena(0);
  160. snes_reset(1);
  161. *fs_path=0;
  162. uint16_t saved_dir_id;
  163. get_db_id(&saved_dir_id);
  164. uint16_t mem_dir_id = sram_readshort(SRAM_DIRID);
  165. uint32_t mem_magic = sram_readlong(SRAM_SCRATCHPAD);
  166. while(0) {
  167. SD_SPI_OFFLOAD=0;
  168. set_avr_addr(0L);
  169. sd_read(0, file_buf, 0L, 1);
  170. uart_trace((void*)file_buf, 0, 0x200);
  171. // sram_writeblock((void*)file_buf, 0, 0x200);
  172. // sram_hexdump(0,0x200);
  173. uart_putc('+');
  174. }
  175. /* here be strange monsters */
  176. while(0){
  177. // uint16_t hurdur1 = 0, hurdur2 = 0;
  178. spiTransferByte(0x00);
  179. spiTransferByte(0x00);
  180. spiTransferByte(0x00);
  181. spiTransferByte(0x00);
  182. spiTransferByte(0x00);
  183. spiTransferByte(0x00);
  184. spiTransferByte(0x00);
  185. spiTransferByte(0x00);
  186. spiTransferByte(0x00);
  187. spiTransferByte(0x00);
  188. spiTransferByte(0x00);
  189. spiTransferByte(0x00);
  190. spiTransferByte(0x00);
  191. PORTB |= _BV(PB2);
  192. DDRB |= _BV(PB2);
  193. PORTB &= ~_BV(PB2);
  194. DDRB &= ~_BV(PB7); // tristate SCK
  195. PORTB |= _BV(PB2);
  196. DDRB &= ~_BV(PB2);
  197. while(!(PINB & _BV(PB2))) {
  198. }
  199. DDRB |= _BV(PB7);
  200. _delay_ms(1);
  201. // dprintf("hurdur1=%d hurdur2=%d\n", hurdur1, hurdur2);
  202. }
  203. if((mem_magic != 0x12345678) || (mem_dir_id != saved_dir_id)) {
  204. uint16_t curr_dir_id = scan_dir(fs_path, 0, 0); // generate files footprint
  205. dprintf("curr dir id = %x\n", curr_dir_id);
  206. if((get_db_id(&saved_dir_id) != FR_OK) // no database?
  207. || saved_dir_id != curr_dir_id) { // files changed? // XXX
  208. dprintf("saved dir id = %x\n", saved_dir_id);
  209. dprintf("rebuilding database...");
  210. _delay_ms(50);
  211. curr_dir_id = scan_dir(fs_path, 1, 0); // then rebuild database
  212. sram_writeblock(&curr_dir_id, SRAM_DB_ADDR, 2);
  213. uint32_t endaddr, direndaddr;
  214. sram_readblock(&endaddr, SRAM_DB_ADDR+4, 4);
  215. sram_readblock(&direndaddr, SRAM_DB_ADDR+8, 4);
  216. dprintf("%lx %lx\n", endaddr, direndaddr);
  217. save_sram((uint8_t*)"/sd2snes/sd2snes.db", endaddr-SRAM_DB_ADDR, SRAM_DB_ADDR);
  218. save_sram((uint8_t*)"/sd2snes/sd2snes.dir", direndaddr-(SRAM_DIR_ADDR), SRAM_DIR_ADDR);
  219. dprintf("done\n");
  220. // sram_hexdump(SRAM_DB_ADDR, 0x400);
  221. } else {
  222. dprintf("saved dir id = %x\n", saved_dir_id);
  223. dprintf("different card, consistent db, loading db...\n");
  224. load_sram((uint8_t*)"/sd2snes/sd2snes.db", SRAM_DB_ADDR);
  225. load_sram((uint8_t*)"/sd2snes/sd2snes.dir", SRAM_DIR_ADDR);
  226. }
  227. // save_sram((uint8_t*)"/debug.smc", 0x400000, 0);
  228. // uart_putc('[');
  229. // load_sram((uint8_t*)"/test.srm", SRAM_SAVE_ADDR);
  230. // uart_putc(']');
  231. sram_writeshort(curr_dir_id, SRAM_DIRID);
  232. sram_writelong(0x12345678, SRAM_SCRATCHPAD);
  233. } else {
  234. dprintf("same card, loading db...\n");
  235. load_sram((uint8_t*)"/sd2snes/sd2snes.db", SRAM_DB_ADDR);
  236. load_sram((uint8_t*)"/sd2snes/sd2snes.dir", SRAM_DIR_ADDR);
  237. }
  238. led_pwm();
  239. // sram_hexdump(0, 0x200);
  240. uart_putc('(');
  241. load_rom((uint8_t*)"/sd2snes/menu.bin", SRAM_MENU_ADDR);
  242. set_rom_mask(0x3fffff); // force mirroring off
  243. set_avr_mapper(0x7); // menu mapper XXX
  244. uart_putc(')');
  245. uart_putcrlf();
  246. // sram_hexdump(0x7ffff0, 0x10);
  247. // sram_hexdump(0, 0x400);
  248. // save_sram((uint8_t*)"/sd2snes/dump", 65536, 0);
  249. sram_writebyte(0, SRAM_CMD_ADDR);
  250. set_busy_led(0);
  251. set_avr_ena(1);
  252. _delay_ms(100);
  253. uart_puts_P(PSTR("SNES GO!\r\n"));
  254. snes_reset(0);
  255. // writetest();
  256. /* snes_reset(1);
  257. set_avr_ena(0);
  258. led_std();
  259. set_busy_led(1);
  260. save_sram((uint8_t*)"/sd2snes/dump", 65536, SRAM_MENU_ADDR);
  261. set_busy_led(0);
  262. set_avr_ena(1);
  263. snes_reset(0); */
  264. uint8_t cmd = 0;
  265. while(!sram_reliable());
  266. while(!cmd) {
  267. cmd=menu_main_loop();
  268. switch(cmd) {
  269. case 0x01: // SNES_CMD_LOADROM:
  270. get_selected_name(file_lfn);
  271. _delay_ms(100);
  272. // snes_reset(1);
  273. set_avr_ena(0);
  274. dprintf("Selected name: %s\n", file_lfn);
  275. load_rom(file_lfn, SRAM_ROM_ADDR);
  276. // save_sram((uint8_t*)"/sd2snes/test.smc", romprops.romsize_bytes, 0);
  277. if(romprops.ramsize_bytes) {
  278. strcpy(strrchr((char*)file_lfn, (int)'.'), ".srm");
  279. dprintf("SRM file: %s\n", file_lfn);
  280. load_sram(file_lfn, SRAM_SAVE_ADDR);
  281. } else {
  282. dprintf("No SRAM\n");
  283. }
  284. set_avr_ena(1);
  285. snes_reset(1);
  286. _delay_ms(100);
  287. snes_reset(0);
  288. break;
  289. default:
  290. dprintf("unknown cmd: %d\n", cmd);
  291. cmd=0; // unknown cmd: stay in loop
  292. break;
  293. }
  294. }
  295. dprintf("cmd was %x, going to snes main loop\n", cmd);
  296. led_std();
  297. cmd=0;
  298. uint8_t snes_reset_prev=0, snes_reset_now=0, snes_reset_state=0;
  299. uint16_t reset_count=0;
  300. while(fpga_test() == FPGA_TEST_TOKEN) {
  301. snes_reset_now=get_snes_reset();
  302. if(snes_reset_now) {
  303. if(!snes_reset_prev) {
  304. dprintf("RESET BUTTON DOWN\n");
  305. snes_reset_state=1;
  306. // reset reset counter
  307. reset_count=0;
  308. }
  309. } else {
  310. if(snes_reset_prev) {
  311. dprintf("RESET BUTTON UP\n");
  312. snes_reset_state=0;
  313. }
  314. }
  315. if(snes_reset_state) {
  316. _delay_ms(10);
  317. reset_count++;
  318. } else {
  319. sram_reliable();
  320. snes_main_loop();
  321. }
  322. if(reset_count>100) {
  323. reset_count=0;
  324. led_std();
  325. set_avr_ena(0);
  326. snes_reset(1);
  327. _delay_ms(100);
  328. if(romprops.ramsize_bytes && fpga_test() == 0xa5) {
  329. set_busy_led(1);
  330. save_sram(file_lfn, romprops.ramsize_bytes, SRAM_SAVE_ADDR);
  331. set_busy_led(0);
  332. }
  333. _delay_ms(1000);
  334. set_busy_led(1);
  335. goto restart;
  336. }
  337. snes_reset_prev = snes_reset_now;
  338. }
  339. // FPGA TEST FAIL. PANIC.
  340. led_panic();
  341. /* HERE BE LIONS */
  342. while(1) {
  343. set_avr_addr(0x600000);
  344. spi_fpga();
  345. spiTransferByte(0x81); // read w/ increment... hopefully
  346. spiTransferByte(0x00); // 1 dummy read
  347. uart_putcrlf();
  348. uint8_t buff[21];
  349. for(uint8_t cnt=0; cnt<21; cnt++) {
  350. uint8_t data=spiTransferByte(0x00);
  351. buff[cnt]=data;
  352. }
  353. for(uint8_t cnt=0; cnt<21; cnt++) {
  354. uint8_t data = buff[cnt];
  355. _delay_ms(2);
  356. if(data>=0x20 && data <= 0x7a) {
  357. uart_putc(data);
  358. } else {
  359. // uart_putc('.');
  360. uart_putc("0123456789ABCDEF"[data>>4]);
  361. uart_putc("0123456789ABCDEF"[data&15]);
  362. uart_putc(' ');
  363. }
  364. // set_avr_bank(3);
  365. }
  366. spi_none();
  367. }
  368. while(1);
  369. }