shell.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489
  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 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. CMD_CRC,
  181. CMD_EXIT,
  182. CMD_RESET,
  183. CMD_RESETSNIFF,
  184. CMD_IRQ,
  185. CMD_AVR,
  186. CMD_SNES,
  187. CMD_LOROM,
  188. CMD_HIROM,
  189. CMD_WR,
  190. CMD_SHMWR,
  191. CMD_SHMSAVE,
  192. CMD_SHMRESTORE,
  193. CMD_LOADER,
  194. CMD_RECONNECT,
  195. CMD_STATUS,
  196. CMD_SYS,
  197. CMD_HELP
  198. };
  199. uint8_t cmdlist[][CMD_HELP] PROGMEM = {
  200. {"DUMP"},
  201. {"DUMPVEC"},
  202. {"DUMPHEADER"},
  203. {"CRC"},
  204. {"EXIT"},
  205. {"RESET"},
  206. {"RESETSNIFF"},
  207. {"IRQ"},
  208. {"AVR"},
  209. {"SNES"},
  210. {"LOROM"},
  211. {"HIROM"},
  212. {"WR"},
  213. {"SHMWR"},
  214. {"SHMSAVE"},
  215. {"SHMRESTORE"},
  216. {"LOADER"},
  217. {"RECONNECT"},
  218. {"STATUS"},
  219. {"SYS"},
  220. {"HELP"},
  221. };
  222. void shell_help(void)
  223. {
  224. uint8_t i;
  225. info_P(PSTR("\n"));
  226. for (i = CMD_DUMP; i < CMD_HELP; i++) {
  227. info_P((PGM_P) cmdlist[i]);
  228. info_P(PSTR("\n"));
  229. }
  230. }
  231. void shell_run(void)
  232. {
  233. uint8_t *t;
  234. uint32_t arg1;
  235. uint32_t arg2;
  236. uint16_t crc;
  237. uint16_t offset;
  238. uint8_t c;
  239. if (!cr)
  240. return;
  241. cr = 0;
  242. strcpy((char *) command_buf, (char *) recv_buf);
  243. token_ptr = command_buf;
  244. t = get_token();
  245. if (t == NULL)
  246. shell_help();
  247. util_strupper(t);
  248. if (strcmp_P((const char *) t, (PGM_P) cmdlist[CMD_DUMP]) == 0) {
  249. if (get_hex_arg2(&arg1, &arg2))
  250. dump_memory(arg1, arg2);
  251. else
  252. info_P(PSTR("DUMP <start addr> <end addr>\n"));
  253. } else if (strcmp_P((char *) t, (PGM_P) cmdlist[CMD_CRC]) == 0) {
  254. if (get_hex_arg2(&arg1, &arg2)) {
  255. crc = crc_check_bulk_memory(arg1, arg2, 0x8000);
  256. info_P(PSTR("0x%06lx - 0x%06lx crc=0x%04x\n"), arg1, arg2, crc);
  257. } else
  258. info_P(PSTR("CRC <start addr> <end addr>\n"));
  259. } else if (strcmp_P((char *) t, (PGM_P) cmdlist[CMD_EXIT]) == 0) {
  260. leave_application();
  261. } else if (strcmp_P((char *) t, (PGM_P) cmdlist[CMD_RESET]) == 0) {
  262. system_send_snes_reset();
  263. } else if (strcmp_P((char *) t, (PGM_P) cmdlist[CMD_IRQ]) == 0) {
  264. info_P(PSTR("Send IRQ\n"));
  265. snes_irq_on();
  266. snes_irq_lo();
  267. _delay_us(20);
  268. snes_irq_hi();
  269. snes_irq_off();
  270. } else if (strcmp_P((char *) t, (PGM_P) cmdlist[CMD_AVR]) == 0) {
  271. system_set_bus_avr();
  272. snes_irq_lo();
  273. system_snes_irq_off();
  274. } else if (strcmp_P((char *) t, (PGM_P) cmdlist[CMD_SNES]) == 0) {
  275. snes_irq_lo();
  276. system_snes_irq_off();
  277. system_set_wr_disable();
  278. system_set_bus_snes();
  279. } else if (strcmp_P((char *) t, (PGM_P) cmdlist[CMD_LOROM]) == 0) {
  280. system_set_rom_lorom();
  281. system_set_wr_disable();
  282. } else if (strcmp_P((char *) t, (PGM_P) cmdlist[CMD_HIROM]) == 0) {
  283. system_set_rom_hirom();
  284. system_set_wr_disable();
  285. } else if (strcmp_P((char *) t, (PGM_P) cmdlist[CMD_WR]) == 0) {
  286. arg1 = get_bool();
  287. if (arg1 == 1) {
  288. info_P(PSTR("Set WR enable"));
  289. snes_wr_enable();
  290. } else if (arg1 == 0) {
  291. info_P(PSTR("Set WR disable"));
  292. snes_wr_disable();
  293. }
  294. } else if (strcmp_P((char *) t, (PGM_P) cmdlist[CMD_RESETSNIFF]) == 0) {
  295. arg1 = get_bool();
  296. if (arg1 == 1) {
  297. info_P(PSTR("Start Reset sniffer"));
  298. irq_init();
  299. } else if (arg1 == 0) {
  300. info_P(PSTR("Stop Reset sniffer"));
  301. irq_stop();
  302. }
  303. } else if (strcmp_P((char *) t, (PGM_P) cmdlist[CMD_DUMPVEC]) == 0) {
  304. uint16_t offset;
  305. if (system.rom_mode == LOROM)
  306. offset = 0x8000;
  307. else
  308. offset = 0x0000;
  309. info_P(PSTR("ABORT 0x%04x 0x%04x\n"), (0xFFE8 - offset),
  310. sram_read16_be(0xFFE8 - offset));
  311. info_P(PSTR("BRK 0x%04x 0x%04x\n"), (0xFFE6 - offset),
  312. sram_read16_be(0xFFE6 - offset));
  313. info_P(PSTR("COP 0x%04x 0x%04x\n"), (0xFFE4 - offset),
  314. sram_read16_be(0xFFE4 - offset));
  315. info_P(PSTR("IRQ 0x%04x 0x%04x\n"), (0xFFEE - offset),
  316. sram_read16_be(0xFFEE - offset));
  317. info_P(PSTR("NMI 0x%04x 0x%04x\n"), (0xFFEA - offset),
  318. sram_read16_be(0xFFEA - offset));
  319. info_P(PSTR("RES 0x%04x 0x%04x\n"), (0xFFFC - offset),
  320. sram_read16_be(0xFFFC - offset));
  321. } else if (strcmp_P((char *) t, (PGM_P) cmdlist[CMD_DUMPHEADER]) == 0) {
  322. if (system.rom_mode == LOROM)
  323. offset = 0x8000;
  324. else
  325. offset = 0x0000;
  326. /*
  327. * # $ffc0..$ffd4 => Name of the ROM, typically in ASCII, using spaces to pad the name to 21 bytes. # $ffd5 => ROM layout,
  328. * typically $20 for LoROM, or $21 for HiROM. Add $10 for FastROM. # $ffd6 => Cartridge type, typically $00 for ROM only, or $02
  329. * for ROM with save-RAM. # $ffd7 => ROM size byte. # $ffd8 => RAM size byte. # $ffd9 => Country code, which selects the video in
  330. * the emulator. Values $00, $01, $0d use NTSC. Values in range $02..$0c use PAL. Other values are invalid. # $ffda => Licensee
  331. * code. If this value is $33, then the ROM has an extended header with ID at $ffb2..$ffb5. # $ffdb => Version number, typically
  332. * $00. # $ffdc..$ffdd => Checksum complement, which is the bitwise-xor of the checksum and $ffff. # $ffde..$ffdf => SNES checksum,
  333. * an unsigned 16-bit checksum of bytes. # $ffe0..$ffe3 => Unknown.
  334. */
  335. info_P(PSTR("NAME 0x%04x "), (0xffc0 - offset));
  336. for (arg1 = (0xffc0 - offset); arg1 < (0xffc0 - offset + 21); arg1++) {
  337. c = sram_read(arg1);
  338. if (c > 0x1f && c < 0x7f)
  339. printf("%c", c);
  340. }
  341. printf("\n");
  342. c = sram_read(0xffd5 - offset);
  343. info_P(PSTR("LAYOUT 0x%04x "), (0xffd5 - offset));
  344. switch (c) {
  345. case 0x20:
  346. info_P(PSTR("LoROM, not fast\n"));
  347. break;
  348. case 0x21:
  349. info_P(PSTR("HiRom, not fast\n"));
  350. break;
  351. case 0x30:
  352. info_P(PSTR("LoROM, fast\n"));
  353. break;
  354. case 0x31:
  355. info_P(PSTR("HiRom, fast\n"));
  356. break;
  357. default:
  358. info_P(PSTR("Unkown 0x%02x\n"), c);
  359. break;
  360. }
  361. c = sram_read(0xffd6 - offset);
  362. info_P(PSTR("TYPE 0x%04xc"), (0xffd6 - offset), c);
  363. switch (c) {
  364. case 0x00:
  365. info_P(PSTR("Rom\n"));
  366. break;
  367. case 0x01:
  368. info_P(PSTR("Rom + Sram\n"));
  369. break;
  370. case 0x02:
  371. info_P(PSTR("Rom + Sram + Battery\n"));
  372. break;
  373. case 0x13:
  374. info_P(PSTR("SuperFX\n"));
  375. break;
  376. case 0x14:
  377. info_P(PSTR("SuperFX\n"));
  378. break;
  379. case 0x15:
  380. info_P(PSTR("SuperFX + Sram\n"));
  381. break;
  382. case 0x1a:
  383. info_P(PSTR("SuperFX + Sram\n"));
  384. break;
  385. case 0x34:
  386. info_P(PSTR("SA-1"));
  387. break;
  388. case 0x35:
  389. info_P(PSTR("SA-1"));
  390. break;
  391. default:
  392. info_P(PSTR("Unkown 0x%02x\n"), c);
  393. break;
  394. }
  395. arg1 = (2 << (sram_read(0xffd7 - offset) - 1));
  396. info_P(PSTR("ROM 0x%04x %li MBit ( %li KiB)\n"),
  397. (0xffd7 - offset), (arg1 / 128), arg1);
  398. arg1 = (2 << (sram_read(0xffd8 - offset) - 1));
  399. info_P(PSTR("RAM 0x%04x %li KiB\n"), (0xffd8 - offset), arg1);
  400. info_P(PSTR("CCODE 0x%04x "), (0xffd9 - offset));
  401. c = sram_read(0xffd9 - offset);
  402. if (c == 0x00 || c == 0x01 || 0x0d)
  403. info_P(PSTR("NTSC\n"));
  404. else if (c >= 0x02 || c <= 0x0c)
  405. info_P(PSTR("PAL\n"));
  406. else
  407. info_P(PSTR("Unkown 0x%02x\n"), c);
  408. info_P(PSTR("LIC 0x%04x 0x%02x\n"), (0xffda - offset),
  409. sram_read(0xffda - offset));
  410. info_P(PSTR("VER 0x%04x 0x%02x\n"), (0xffdb - offset),
  411. sram_read(0xffdb - offset));
  412. info_P(PSTR("SUM1 0x%04x 0x%04x\n"), (0xffdc - offset),
  413. sram_read16_be(0xffdc - offset));
  414. info_P(PSTR("SUM2 0x%04x 0x%04x\n"), (0xffde - offset),
  415. sram_read16_be(0xffde - offset));
  416. } else if (strcmp_P((char *) t, (PGM_P) cmdlist[CMD_SHMWR]) == 0) {
  417. if (get_hex_arg2(&arg1, &arg2))
  418. shared_memory_write((uint8_t) arg1, (uint8_t) arg1);
  419. else
  420. info_P(PSTR("SHMWR <command> <value>\n"));
  421. } else if (strcmp_P((char *) t, (PGM_P) cmdlist[CMD_SHMSAVE]) == 0) {
  422. shared_memory_scratchpad_region_tx_save();
  423. shared_memory_scratchpad_region_rx_save();
  424. info_P(PSTR("Save scratchpad\n"));
  425. } else if (strcmp_P((char *) t, (PGM_P) cmdlist[CMD_SHMRESTORE]) == 0) {
  426. shared_memory_scratchpad_region_tx_restore();
  427. shared_memory_scratchpad_region_rx_restore();
  428. info_P(PSTR("Restore scratchpad\n"));
  429. } else if (strcmp_P((char *) t, (PGM_P) cmdlist[CMD_LOADER]) == 0) {
  430. boot_startup_rom(500);
  431. } else if (strcmp_P((char *) t, (PGM_P) cmdlist[CMD_RECONNECT]) == 0) {
  432. usb_connect();
  433. } else if (strcmp_P((char *) t, (PGM_P) cmdlist[CMD_STATUS]) == 0) {
  434. transaction_status();
  435. } else if (strcmp_P((char *) t, (PGM_P) cmdlist[CMD_SYS]) == 0) {
  436. system_status();
  437. } else if (strcmp_P((char *) t, (PGM_P) cmdlist[CMD_HELP]) == 0) {
  438. shell_help();
  439. }
  440. prompt();
  441. }
  442. #endif