shell.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495
  1. /*
  2. * =====================================================================================
  3. *
  4. * ________ .__ __ ________ ____ ________
  5. * \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
  6. * / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
  7. * / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
  8. * \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
  9. * \__> \/ \/ \/ \/ \/
  10. *
  11. * www.optixx.org
  12. *
  13. *
  14. * Version: 1.0
  15. * Created: 07/21/2009 03:32:16 PM
  16. * Author: david@optixx.org
  17. *
  18. * =====================================================================================
  19. */
  20. #include <stdint.h>
  21. #include <string.h>
  22. #include <avr/io.h>
  23. #include <stdlib.h>
  24. #include <avr/interrupt.h>
  25. #include <util/delay.h>
  26. #include <avr/pgmspace.h>
  27. #include <avr/eeprom.h>
  28. #include "pwm.h"
  29. #include "debug.h"
  30. #include "info.h"
  31. #include "sram.h"
  32. #include "util.h"
  33. #include "uart.h"
  34. #include "dump.h"
  35. #include "irq.h"
  36. #include "config.h"
  37. #include "crc.h"
  38. #include "command.h"
  39. #include "shared_memory.h"
  40. #include "system.h"
  41. extern system_t my_system;
  42. const char STR_ROM[] PROGMEM = "Rom";
  43. const char STR_RAM[] PROGMEM = "Sram";
  44. const char STR_BAT[] PROGMEM = "Battery";
  45. const char STR_SUPERFX[] PROGMEM = "SuperFX";
  46. const char STR_SA[] PROGMEM = "SA-1";
  47. uint8_t command_buf[RECEIVE_BUF_LEN];
  48. uint8_t recv_buf[RECEIVE_BUF_LEN];
  49. volatile uint8_t recv_counter = 0;
  50. volatile uint8_t cr = 0;
  51. uint8_t *token_ptr;
  52. #if DO_SHELL
  53. uint8_t *get_token(void)
  54. {
  55. uint8_t *p = token_ptr;
  56. while (*p == ' ')
  57. p++;
  58. if (*p == '\0')
  59. return NULL;
  60. token_ptr = p;
  61. do {
  62. token_ptr++;
  63. if (*token_ptr == ' ' || *token_ptr == '\n' || *token_ptr == '\r') {
  64. *token_ptr++ = '\0';
  65. break;
  66. }
  67. } while (*token_ptr != ' ' && *token_ptr != '\n' && *token_ptr != '\r');
  68. return p;
  69. }
  70. uint8_t get_dec(uint32_t * decval)
  71. {
  72. const uint8_t *t;
  73. t = get_token();
  74. if (t != NULL) {
  75. int x = util_sscandec(t);
  76. if (x < 0)
  77. return 0;
  78. *decval = x;
  79. return 1;
  80. }
  81. return 0;
  82. }
  83. uint8_t parse_hex(const uint8_t * s, uint32_t * hexval)
  84. {
  85. uint32_t x = util_sscanhex(s);
  86. *hexval = (uint32_t) x;
  87. return 1;
  88. }
  89. uint8_t get_hex(uint32_t * hexval)
  90. {
  91. const uint8_t *t;
  92. t = get_token();
  93. if (t != NULL)
  94. return parse_hex(t, hexval);
  95. return 0;
  96. }
  97. uint8_t get_hex_arg2(uint32_t * hexval1, uint32_t * hexval2)
  98. {
  99. return get_hex(hexval1) && get_hex(hexval2);
  100. }
  101. uint8_t get_hex_arg3(uint32_t * hexval1, uint32_t * hexval2, uint32_t * hexval3)
  102. {
  103. return get_hex(hexval1) && get_hex(hexval2) && get_hex(hexval3);
  104. }
  105. #if 0
  106. static uint8_t get_int32(uint32_t * val)
  107. {
  108. if (!get_hex(val)) {
  109. info_P(PSTR("Invalid argument!\n"));
  110. return 0;
  111. } else {
  112. return 1;
  113. }
  114. }
  115. static uint8_t get_int8(uint8_t * val)
  116. {
  117. uint32_t ret;
  118. if (!get_hex(&ret) || ret > 0xff) {
  119. info_P(PSTR("Invalid argument!\n"));
  120. return 0;
  121. } else {
  122. *val = (uint8_t) ret;
  123. return 1;
  124. }
  125. }
  126. #endif
  127. static int get_bool(void)
  128. {
  129. const uint8_t *t;
  130. t = get_token();
  131. if (t != NULL) {
  132. int result = util_sscanbool(t);
  133. if (result >= 0)
  134. return result;
  135. }
  136. info_P(PSTR("Invalid argument (should be 0 or 1)!\n"));
  137. return -1;
  138. }
  139. void prompt(void)
  140. {
  141. uart_putc('\r');
  142. uart_putc('\n');
  143. uart_putc('>');
  144. }
  145. ISR(USART0_RX_vect)
  146. {
  147. UCSR0B &= (255 - (1 << RXCIE0)); // Interrupts disable for RxD
  148. sei();
  149. if (recv_counter == (sizeof(recv_buf) - 1)) {
  150. cr = 1;
  151. recv_buf[recv_counter] = '\0';
  152. recv_counter = 0;
  153. prompt();
  154. }
  155. recv_buf[recv_counter] = UDR0;
  156. uart_putc(recv_buf[recv_counter]);
  157. if (recv_buf[recv_counter] == 0x0d) {
  158. /*
  159. * recv_buf[recv_counter] = 0;
  160. */
  161. cr = 1;
  162. recv_buf[++recv_counter] = '\0';
  163. recv_counter = 0;
  164. prompt();
  165. } else {
  166. // we accept backspace or delete
  167. if ((recv_buf[recv_counter] == 0x08 || recv_buf[recv_counter] == 0x7f)
  168. && recv_counter > 0) {
  169. recv_counter--;
  170. } else {
  171. recv_counter++;
  172. }
  173. }
  174. UCSR0B |= (1 << RXCIE0);
  175. }
  176. enum cmds {
  177. CMD_DUMP,
  178. CMD_DUMPVEC,
  179. CMD_DUMPHEADER,
  180. #if DO_CRC_CHECK
  181. CMD_CRC,
  182. #endif
  183. CMD_EXIT,
  184. CMD_RESET,
  185. CMD_RESETSNIFF,
  186. CMD_IRQ,
  187. CMD_AVR,
  188. CMD_SNES,
  189. CMD_LOROM,
  190. CMD_HIROM,
  191. CMD_WR,
  192. CMD_SHMWR,
  193. CMD_SHMSAVE,
  194. CMD_SHMRESTORE,
  195. CMD_LOADER,
  196. CMD_RECONNECT,
  197. CMD_STATUS,
  198. CMD_SYS,
  199. CMD_HELP
  200. };
  201. const uint8_t cmdlist[][CMD_HELP] PROGMEM = {
  202. {"DUMP"},
  203. {"DUMPVEC"},
  204. {"DUMPHEADER"},
  205. #if DO_CRC_CHECK
  206. {"CRC"},
  207. #endif
  208. {"EXIT"},
  209. {"RESET"},
  210. {"RESETSNIFF"},
  211. {"IRQ"},
  212. {"AVR"},
  213. {"SNES"},
  214. {"LOROM"},
  215. {"HIROM"},
  216. {"WR"},
  217. {"SHMWR"},
  218. {"SHMSAVE"},
  219. {"SHMRESTORE"},
  220. {"LOADER"},
  221. {"RECONNECT"},
  222. {"STATUS"},
  223. {"SYS"},
  224. {"HELP"},
  225. };
  226. void shell_help(void)
  227. {
  228. uint8_t i;
  229. info_P(PSTR("\n"));
  230. for (i = CMD_DUMP; i < CMD_HELP; i++) {
  231. info_P((PGM_P) cmdlist[i]);
  232. info_P(PSTR("\n"));
  233. }
  234. }
  235. void shell_run(void)
  236. {
  237. uint8_t *t;
  238. uint32_t arg1;
  239. uint32_t arg2;
  240. uint16_t crc;
  241. uint16_t offset;
  242. uint8_t c;
  243. if (!cr)
  244. return;
  245. cr = 0;
  246. strcpy((char *) command_buf, (char *) recv_buf);
  247. token_ptr = command_buf;
  248. t = get_token();
  249. if (t == NULL)
  250. shell_help();
  251. util_strupper(t);
  252. if (strcmp_P((const char *) t, (PGM_P) cmdlist[CMD_DUMP]) == 0) {
  253. if (get_hex_arg2(&arg1, &arg2))
  254. dump_memory(arg1, arg2);
  255. else
  256. info_P(PSTR("DUMP <start addr> <end addr>\n"));
  257. #if DO_CRC_CHECK
  258. } else if (strcmp_P((char *) t, (PGM_P) cmdlist[CMD_CRC]) == 0) {
  259. if (get_hex_arg2(&arg1, &arg2)) {
  260. crc = crc_check_bulk_memory(arg1, arg2, 0x8000);
  261. info_P(PSTR("0x%06lx - 0x%06lx crc=0x%04x\n"), arg1, arg2, crc);
  262. } else
  263. info_P(PSTR("CRC <start addr> <end addr>\n"));
  264. #endif
  265. } else if (strcmp_P((char *) t, (PGM_P) cmdlist[CMD_EXIT]) == 0) {
  266. leave_application();
  267. } else if (strcmp_P((char *) t, (PGM_P) cmdlist[CMD_RESET]) == 0) {
  268. system_send_snes_reset();
  269. } else if (strcmp_P((char *) t, (PGM_P) cmdlist[CMD_IRQ]) == 0) {
  270. info_P(PSTR("Send IRQ\n"));
  271. snes_irq_on();
  272. snes_irq_lo();
  273. _delay_us(20);
  274. snes_irq_hi();
  275. snes_irq_off();
  276. } else if (strcmp_P((char *) t, (PGM_P) cmdlist[CMD_AVR]) == 0) {
  277. system_set_bus_avr();
  278. snes_irq_lo();
  279. system_snes_irq_off();
  280. } else if (strcmp_P((char *) t, (PGM_P) cmdlist[CMD_SNES]) == 0) {
  281. snes_irq_lo();
  282. system_snes_irq_off();
  283. system_set_wr_disable();
  284. system_set_bus_snes();
  285. } else if (strcmp_P((char *) t, (PGM_P) cmdlist[CMD_LOROM]) == 0) {
  286. system_set_rom_lorom();
  287. system_set_wr_disable();
  288. } else if (strcmp_P((char *) t, (PGM_P) cmdlist[CMD_HIROM]) == 0) {
  289. system_set_rom_hirom();
  290. system_set_wr_disable();
  291. } else if (strcmp_P((char *) t, (PGM_P) cmdlist[CMD_WR]) == 0) {
  292. arg1 = get_bool();
  293. if (arg1 == 1) {
  294. info_P(PSTR("Set WR enable"));
  295. snes_wr_enable();
  296. } else if (arg1 == 0) {
  297. info_P(PSTR("Set WR disable"));
  298. snes_wr_disable();
  299. }
  300. } else if (strcmp_P((char *) t, (PGM_P) cmdlist[CMD_RESETSNIFF]) == 0) {
  301. arg1 = get_bool();
  302. if (arg1 == 1) {
  303. info_P(PSTR("Start Reset sniffer"));
  304. irq_init();
  305. } else if (arg1 == 0) {
  306. info_P(PSTR("Stop Reset sniffer"));
  307. irq_stop();
  308. }
  309. } else if (strcmp_P((char *) t, (PGM_P) cmdlist[CMD_DUMPVEC]) == 0) {
  310. uint16_t offset;
  311. if (my_system.rom_mode == LOROM)
  312. offset = 0x8000;
  313. else
  314. offset = 0x0000;
  315. info_P(PSTR("ABORT 0x%04x 0x%04x\n"), (0xFFE8 - offset),
  316. sram_read16_be(0xFFE8 - offset));
  317. info_P(PSTR("BRK 0x%04x 0x%04x\n"), (0xFFE6 - offset),
  318. sram_read16_be(0xFFE6 - offset));
  319. info_P(PSTR("COP 0x%04x 0x%04x\n"), (0xFFE4 - offset),
  320. sram_read16_be(0xFFE4 - offset));
  321. info_P(PSTR("IRQ 0x%04x 0x%04x\n"), (0xFFEE - offset),
  322. sram_read16_be(0xFFEE - offset));
  323. info_P(PSTR("NMI 0x%04x 0x%04x\n"), (0xFFEA - offset),
  324. sram_read16_be(0xFFEA - offset));
  325. info_P(PSTR("RES 0x%04x 0x%04x\n"), (0xFFFC - offset),
  326. sram_read16_be(0xFFFC - offset));
  327. } else if (strcmp_P((char *) t, (PGM_P) cmdlist[CMD_DUMPHEADER]) == 0) {
  328. if (my_system.rom_mode == LOROM)
  329. offset = 0x8000;
  330. else
  331. offset = 0x0000;
  332. /*
  333. * # $ffc0..$ffd4 => Name of the ROM, typically in ASCII, using spaces to pad the name to 21 bytes. # $ffd5 => ROM layout,
  334. * typically $20 for LoROM, or $21 for HiROM. Add $10 for FastROM. # $ffd6 => Cartridge type, typically $00 for ROM only, or $02
  335. * for ROM with save-RAM. # $ffd7 => ROM size byte. # $ffd8 => RAM size byte. # $ffd9 => Country code, which selects the video in
  336. * the emulator. Values $00, $01, $0d use NTSC. Values in range $02..$0c use PAL. Other values are invalid. # $ffda => Licensee
  337. * code. If this value is $33, then the ROM has an extended header with ID at $ffb2..$ffb5. # $ffdb => Version number, typically
  338. * $00. # $ffdc..$ffdd => Checksum complement, which is the bitwise-xor of the checksum and $ffff. # $ffde..$ffdf => SNES checksum,
  339. * an unsigned 16-bit checksum of bytes. # $ffe0..$ffe3 => Unknown.
  340. */
  341. info_P(PSTR("NAME 0x%04x "), (0xffc0 - offset));
  342. for (arg1 = (0xffc0 - offset); arg1 < (0xffc0 - offset + 21); arg1++) {
  343. c = sram_read(arg1);
  344. if (c > 0x1f && c < 0x7f)
  345. printf("%c", c);
  346. }
  347. printf("\n");
  348. c = sram_read(0xffd5 - offset);
  349. info_P(PSTR("LAYOUT 0x%04x "), (0xffd5 - offset));
  350. switch (c) {
  351. case 0x20:
  352. info_P(PSTR("LoROM, not fast\n"));
  353. break;
  354. case 0x21:
  355. info_P(PSTR("HiRom, not fast\n"));
  356. break;
  357. case 0x30:
  358. info_P(PSTR("LoROM, fast\n"));
  359. break;
  360. case 0x31:
  361. info_P(PSTR("HiRom, fast\n"));
  362. break;
  363. default:
  364. info_P(PSTR("Unkown 0x%02x\n"), c);
  365. break;
  366. }
  367. c = sram_read(0xffd6 - offset);
  368. info_P(PSTR("TYPE 0x%04xc"), (0xffd6 - offset), c);
  369. switch (c) {
  370. case 0x00:
  371. info_P(PSTR("Rom\n"));
  372. break;
  373. case 0x01:
  374. info_P(PSTR("Rom + Sram\n"));
  375. break;
  376. case 0x02:
  377. info_P(PSTR("Rom + Sram + Battery\n"));
  378. break;
  379. case 0x13:
  380. info_P(PSTR("SuperFX\n"));
  381. break;
  382. case 0x14:
  383. info_P(PSTR("SuperFX\n"));
  384. break;
  385. case 0x15:
  386. info_P(PSTR("SuperFX + Sram\n"));
  387. break;
  388. case 0x1a:
  389. info_P(PSTR("SuperFX + Sram\n"));
  390. break;
  391. case 0x34:
  392. info_P(PSTR("SA-1"));
  393. break;
  394. case 0x35:
  395. info_P(PSTR("SA-1"));
  396. break;
  397. default:
  398. info_P(PSTR("Unkown 0x%02x\n"), c);
  399. break;
  400. }
  401. arg1 = (2 << (sram_read(0xffd7 - offset) - 1));
  402. info_P(PSTR("ROM 0x%04x %li MBit ( %li KiB)\n"),
  403. (0xffd7 - offset), (arg1 / 128), arg1);
  404. arg1 = (2 << (sram_read(0xffd8 - offset) - 1));
  405. info_P(PSTR("RAM 0x%04x %li KiB\n"), (0xffd8 - offset), arg1);
  406. info_P(PSTR("CCODE 0x%04x "), (0xffd9 - offset));
  407. c = sram_read(0xffd9 - offset);
  408. if (c == 0x00 || c == 0x01 || 0x0d)
  409. info_P(PSTR("NTSC\n"));
  410. else if (c >= 0x02 || c <= 0x0c)
  411. info_P(PSTR("PAL\n"));
  412. else
  413. info_P(PSTR("Unkown 0x%02x\n"), c);
  414. info_P(PSTR("LIC 0x%04x 0x%02x\n"), (0xffda - offset),
  415. sram_read(0xffda - offset));
  416. info_P(PSTR("VER 0x%04x 0x%02x\n"), (0xffdb - offset),
  417. sram_read(0xffdb - offset));
  418. info_P(PSTR("SUM1 0x%04x 0x%04x\n"), (0xffdc - offset),
  419. sram_read16_be(0xffdc - offset));
  420. info_P(PSTR("SUM2 0x%04x 0x%04x\n"), (0xffde - offset),
  421. sram_read16_be(0xffde - offset));
  422. } else if (strcmp_P((char *) t, (PGM_P) cmdlist[CMD_SHMWR]) == 0) {
  423. if (get_hex_arg2(&arg1, &arg2))
  424. shared_memory_write((uint8_t) arg1, (uint8_t) arg1);
  425. else
  426. info_P(PSTR("SHMWR <command> <value>\n"));
  427. } else if (strcmp_P((char *) t, (PGM_P) cmdlist[CMD_SHMSAVE]) == 0) {
  428. shared_memory_scratchpad_region_tx_save();
  429. shared_memory_scratchpad_region_rx_save();
  430. info_P(PSTR("Save scratchpad\n"));
  431. } else if (strcmp_P((char *) t, (PGM_P) cmdlist[CMD_SHMRESTORE]) == 0) {
  432. shared_memory_scratchpad_region_tx_restore();
  433. shared_memory_scratchpad_region_rx_restore();
  434. info_P(PSTR("Restore scratchpad\n"));
  435. } else if (strcmp_P((char *) t, (PGM_P) cmdlist[CMD_LOADER]) == 0) {
  436. boot_startup_rom(500);
  437. } else if (strcmp_P((char *) t, (PGM_P) cmdlist[CMD_RECONNECT]) == 0) {
  438. usb_connect();
  439. } else if (strcmp_P((char *) t, (PGM_P) cmdlist[CMD_STATUS]) == 0) {
  440. transaction_status();
  441. } else if (strcmp_P((char *) t, (PGM_P) cmdlist[CMD_SYS]) == 0) {
  442. system_status();
  443. } else if (strcmp_P((char *) t, (PGM_P) cmdlist[CMD_HELP]) == 0) {
  444. shell_help();
  445. }
  446. prompt();
  447. }
  448. #endif