snes.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. // insert cool lengthy disclaimer here
  2. // snes.c: SNES hardware control (resetting)
  3. #include <avr/io.h>
  4. #include "avrcompat.h"
  5. #include "config.h"
  6. #include "uart.h"
  7. #include "snes.h"
  8. #include "memory.h"
  9. #include "fileops.h"
  10. #include "ff.h"
  11. #include "led.h"
  12. #include "smc.h"
  13. uint8_t initloop=1;
  14. uint32_t saveram_crc, saveram_crc_old;
  15. uint32_t saveram_base_addr = 0x600000; // chip 3
  16. void snes_init() {
  17. DDRD |= _BV(PD5); // PD5 = RESET_DIR
  18. DDRD |= _BV(PD6); // PD6 = RESET
  19. snes_reset(1);
  20. }
  21. /*
  22. * sets the SNES reset state.
  23. *
  24. * state: put SNES in reset state when 1, release when 0
  25. */
  26. void snes_reset(int state) {
  27. if(state) {
  28. DDRD |= _BV(PD6); // /RESET pin -> out
  29. PORTD &= ~_BV(PD6); // /RESET = 0
  30. PORTD |= _BV(PD5); // RESET_DIR = 1;
  31. } else {
  32. PORTD &= ~_BV(PD5); // RESET_DIR = 0;
  33. DDRD &= ~_BV(PD6); // /RESET pin -> in
  34. PORTD |= _BV(PD6); // /RESET = pullup
  35. }
  36. }
  37. /*
  38. * gets the SNES reset state.
  39. *
  40. * returns: 1 when reset, 0 when not reset
  41. */
  42. uint8_t get_snes_reset() {
  43. // DDRD &= ~_BV(PD6); // /RESET pin -> in
  44. // PORTD &= ~_BV(PD5); // RESET_DIR (external buffer) = 0
  45. return !(PIND & _BV(PD6));
  46. }
  47. /*
  48. * SD2SNES main loop.
  49. * monitors SRAM changes and other things
  50. */
  51. uint32_t diffcount = 0, samecount = 0, didnotsave = 0;
  52. uint8_t sram_valid = 0;
  53. void snes_main_loop() {
  54. if(!romprops.ramsize_bytes)return;
  55. if(initloop) {
  56. saveram_crc_old = calc_sram_crc(saveram_base_addr, romprops.ramsize_bytes);
  57. initloop=0;
  58. }
  59. saveram_crc = calc_sram_crc(saveram_base_addr, romprops.ramsize_bytes);
  60. sram_valid = sram_reliable();
  61. if(crc_valid && sram_valid) {
  62. if(saveram_crc != saveram_crc_old) {
  63. if(samecount) {
  64. diffcount=1;
  65. } else {
  66. diffcount++;
  67. didnotsave++;
  68. }
  69. samecount=0;
  70. }
  71. if(saveram_crc == saveram_crc_old) {
  72. samecount++;
  73. }
  74. if(diffcount>=1 && samecount==5) {
  75. uart_putc('U');
  76. uart_puthexshort(saveram_crc);
  77. uart_putcrlf();
  78. set_busy_led(1);
  79. save_sram(file_lfn, romprops.ramsize_bytes, saveram_base_addr);
  80. set_busy_led(0);
  81. didnotsave=0;
  82. }
  83. if(didnotsave>50) {
  84. diffcount=0;
  85. uart_putc('V');
  86. set_busy_led(1);
  87. save_sram(file_lfn, romprops.ramsize_bytes, saveram_base_addr);
  88. didnotsave=0;
  89. set_busy_led(0);
  90. }
  91. saveram_crc_old = saveram_crc;
  92. }
  93. dprintf("crc_valid=%d sram_valid=%d diffcount=%ld samecount=%ld, didnotsave=%ld\n", crc_valid, sram_valid, diffcount, samecount, didnotsave);
  94. }
  95. /*
  96. * SD2SNES menu loop.
  97. * monitors menu selection. return when selection was made.
  98. */
  99. uint8_t menu_main_loop() {
  100. uint8_t cmd = 0;
  101. sram_writebyte(0, SRAM_CMD_ADDR);
  102. while(!cmd) {
  103. if(!get_snes_reset()) {
  104. while(!sram_reliable());
  105. cmd = sram_readbyte(SRAM_CMD_ADDR);
  106. }
  107. if(get_snes_reset()) {
  108. cmd = 0;
  109. }
  110. }
  111. return cmd;
  112. }
  113. void get_selected_name(uint8_t* fn) {
  114. uint32_t addr = sram_readlong(SRAM_FD_ADDR);
  115. dprintf("fd addr=%lX\n", addr);
  116. sram_readblock(fn, addr+0x41, 256);
  117. }