shell.c 14 KB

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