mirror of
https://github.com/sanni/cartreader.git
synced 2025-03-01 10:55:23 +01:00
Fix reading/writing 4MB HiROM
HiROM starts at bank 192 and has 64 banks so byte variable currBank overflows.
This commit is contained in:
parent
a3feb32e15
commit
cc17c70e30
@ -109,7 +109,7 @@ char ver[5] = "11.1";
|
|||||||
#define enable_PCE
|
#define enable_PCE
|
||||||
|
|
||||||
// Benesse Pocket Challenge W
|
// Benesse Pocket Challenge W
|
||||||
//#define enable_PCW
|
#define enable_PCW
|
||||||
|
|
||||||
// Sega Master System
|
// Sega Master System
|
||||||
#define enable_SMS
|
#define enable_SMS
|
||||||
@ -127,10 +127,10 @@ char ver[5] = "11.1";
|
|||||||
#define enable_VBOY
|
#define enable_VBOY
|
||||||
|
|
||||||
// WonderSwan
|
// WonderSwan
|
||||||
//#define enable_WS
|
#define enable_WS
|
||||||
|
|
||||||
// Watara Supervision
|
// Watara Supervision
|
||||||
//#define enable_WSV
|
#define enable_WSV
|
||||||
|
|
||||||
//******************************************
|
//******************************************
|
||||||
// HW CONFIGS
|
// HW CONFIGS
|
||||||
@ -298,9 +298,9 @@ bool i2c_found;
|
|||||||
#include "FreqCount.h"
|
#include "FreqCount.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void _print_FatalError(void) __attribute__ ((noreturn));
|
void _print_FatalError(void) __attribute__((noreturn));
|
||||||
void print_FatalError(const __FlashStringHelper* errorMessage) __attribute__ ((noreturn));
|
void print_FatalError(const __FlashStringHelper* errorMessage) __attribute__((noreturn));
|
||||||
void print_FatalError(byte errorMessage) __attribute__ ((noreturn));
|
void print_FatalError(byte errorMessage) __attribute__((noreturn));
|
||||||
|
|
||||||
/******************************************
|
/******************************************
|
||||||
Common Strings
|
Common Strings
|
||||||
@ -495,7 +495,7 @@ byte sdBuffer[512];
|
|||||||
|
|
||||||
// soft reset Arduino: jumps to 0
|
// soft reset Arduino: jumps to 0
|
||||||
// using the watchdog timer would be more elegant but some Mega2560 bootloaders are buggy with it
|
// using the watchdog timer would be more elegant but some Mega2560 bootloaders are buggy with it
|
||||||
void (*resetArduino)(void) __attribute__ ((noreturn)) = 0;
|
void (*resetArduino)(void) __attribute__((noreturn)) = 0;
|
||||||
|
|
||||||
// Progressbar
|
// Progressbar
|
||||||
void draw_progressbar(uint32_t processedsize, uint32_t totalsize);
|
void draw_progressbar(uint32_t processedsize, uint32_t totalsize);
|
||||||
@ -1074,7 +1074,7 @@ void mainMenu() {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
print_MissingModule(); // does not return
|
print_MissingModule(); // does not return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1168,7 +1168,7 @@ void mainMenu() {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
print_MissingModule(); // does not return
|
print_MissingModule(); // does not return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1207,7 +1207,7 @@ void addonMenu() {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
print_MissingModule(); // does not return
|
print_MissingModule(); // does not return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1263,7 +1263,7 @@ void consoleMenu() {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
print_MissingModule(); // does not return
|
print_MissingModule(); // does not return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1321,7 +1321,7 @@ void handheldMenu() {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
print_MissingModule(); // does not return
|
print_MissingModule(); // does not return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -1983,7 +1983,7 @@ void print_FatalError(const __FlashStringHelper* errorMessage) {
|
|||||||
_print_FatalError();
|
_print_FatalError();
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_FatalError(byte errorMessage){
|
void print_FatalError(byte errorMessage) {
|
||||||
print_Error(errorMessage);
|
print_Error(errorMessage);
|
||||||
_print_FatalError();
|
_print_FatalError();
|
||||||
}
|
}
|
||||||
|
@ -565,12 +565,12 @@ void writeByte_GBA(unsigned long myAddress, byte myData) {
|
|||||||
*****************************************/
|
*****************************************/
|
||||||
// Compute the checksum of rom header
|
// Compute the checksum of rom header
|
||||||
// "header" must contain at least the rom's first 188 bytes
|
// "header" must contain at least the rom's first 188 bytes
|
||||||
byte checksumHeader_GBA(const byte *header) {
|
byte checksumHeader_GBA(const byte* header) {
|
||||||
byte result = 0x00;
|
byte result = 0x00;
|
||||||
for (byte n = 0xA0; n < 0xBD; n++) {
|
for (byte n = 0xA0; n < 0xBD; n++) {
|
||||||
result -= header[n];
|
result -= header[n];
|
||||||
}
|
}
|
||||||
return result - 0x19;
|
return result - 0x19;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read info out of rom header
|
// Read info out of rom header
|
||||||
|
@ -586,7 +586,7 @@ void writeWord_N64(word myWord) {
|
|||||||
*****************************************/
|
*****************************************/
|
||||||
static word addrCRC(word address) {
|
static word addrCRC(word address) {
|
||||||
const char n64_address_crc_table[] = { 0x15, 0x1F, 0x0B, 0x16, 0x19, 0x07, 0x0E, 0x1C, 0x0D, 0x1A, 0x01 };
|
const char n64_address_crc_table[] = { 0x15, 0x1F, 0x0B, 0x16, 0x19, 0x07, 0x0E, 0x1C, 0x0D, 0x1A, 0x01 };
|
||||||
const char *cur_xor = n64_address_crc_table;
|
const char* cur_xor = n64_address_crc_table;
|
||||||
byte crc = 0;
|
byte crc = 0;
|
||||||
for (word mask = 0x0020; mask; mask <<= 1, cur_xor++) {
|
for (word mask = 0x0020; mask; mask <<= 1, cur_xor++) {
|
||||||
if (address & mask) {
|
if (address & mask) {
|
||||||
@ -618,23 +618,23 @@ static uint8_t dataCRC(uint8_t* data) {
|
|||||||
// (3 instructions) making it the same size as the equivalent 3-cycles NOP
|
// (3 instructions) making it the same size as the equivalent 3-cycles NOP
|
||||||
// delay. For shorter delays or non-multiple-of-3-cycle delays, add your own
|
// delay. For shorter delays or non-multiple-of-3-cycle delays, add your own
|
||||||
// NOPs.
|
// NOPs.
|
||||||
#define N64_DELAY_LOOP(cycle_count) do { \
|
#define N64_DELAY_LOOP(cycle_count) \
|
||||||
byte i; \
|
do { \
|
||||||
__asm__ __volatile__ ("\n" \
|
byte i; \
|
||||||
"\tldi %[i], %[loop_count]\n" \
|
__asm__ __volatile__("\n" \
|
||||||
".delay_loop_%=:\n" \
|
"\tldi %[i], %[loop_count]\n" \
|
||||||
"\tdec %[i]\n" \
|
".delay_loop_%=:\n" \
|
||||||
"\tbrne .delay_loop_%=\n" \
|
"\tdec %[i]\n" \
|
||||||
: [i] "=r" (i) \
|
"\tbrne .delay_loop_%=\n" \
|
||||||
: [loop_count] "i" (cycle_count / 3) \
|
: [i] "=r"(i) \
|
||||||
: "cc" \
|
: [loop_count] "i"(cycle_count / 3) \
|
||||||
); \
|
: "cc"); \
|
||||||
} while(0)
|
} while (0)
|
||||||
|
|
||||||
/******************************************
|
/******************************************
|
||||||
N64 Controller Protocol Functions
|
N64 Controller Protocol Functions
|
||||||
*****************************************/
|
*****************************************/
|
||||||
void sendJoyBus(const byte *buffer, char length) {
|
void sendJoyBus(const byte* buffer, char length) {
|
||||||
// Implemented in assembly as there is very little wiggle room, timing-wise.
|
// Implemented in assembly as there is very little wiggle room, timing-wise.
|
||||||
// Overall structure:
|
// Overall structure:
|
||||||
// outer_loop:
|
// outer_loop:
|
||||||
@ -678,130 +678,129 @@ void sendJoyBus(const byte *buffer, char length) {
|
|||||||
const byte line_low = DDRH | 0x10;
|
const byte line_low = DDRH | 0x10;
|
||||||
const byte line_high = line_low & 0xef;
|
const byte line_high = line_low & 0xef;
|
||||||
__asm__ __volatile__("\n"
|
__asm__ __volatile__("\n"
|
||||||
".outer_loop_%=:\n"
|
".outer_loop_%=:\n"
|
||||||
// mask = 0x80
|
// mask = 0x80
|
||||||
"\tldi %[mask], 0x80\n" // 1
|
"\tldi %[mask], 0x80\n" // 1
|
||||||
// load byte to send from memory
|
// load byte to send from memory
|
||||||
"\tld %[cur_byte], Z+\n" // 2
|
"\tld %[cur_byte], Z+\n" // 2
|
||||||
".inner_loop_%=:\n"
|
".inner_loop_%=:\n"
|
||||||
// Falling edge
|
// Falling edge
|
||||||
"\tsts %[out_byte], %[line_low]\n" // 2
|
"\tsts %[out_byte], %[line_low]\n" // 2
|
||||||
// Test cur_byte & mask, without clobbering either
|
// Test cur_byte & mask, without clobbering either
|
||||||
"\tmov %[scratch], %[cur_byte]\n" // 1
|
"\tmov %[scratch], %[cur_byte]\n" // 1
|
||||||
"\tand %[scratch], %[mask]\n" // 1
|
"\tand %[scratch], %[mask]\n" // 1
|
||||||
"\tbreq .bit_is_0_%=\n" // bit is 1: 1, bit is 0: 2
|
"\tbreq .bit_is_0_%=\n" // bit is 1: 1, bit is 0: 2
|
||||||
|
|
||||||
// bit is a 1
|
// bit is a 1
|
||||||
// Stay low for 1us (16 cycles).
|
// Stay low for 1us (16 cycles).
|
||||||
// Time before: 3 cycles (mov, and, breq-false).
|
// Time before: 3 cycles (mov, and, breq-false).
|
||||||
// Time after: sts (2 cycles).
|
// Time after: sts (2 cycles).
|
||||||
// So 11 to go, so 3 3-cycles iterations and 2 nop.
|
// So 11 to go, so 3 3-cycles iterations and 2 nop.
|
||||||
"\tldi %[scratch], 3\n" // 1
|
"\tldi %[scratch], 3\n" // 1
|
||||||
".delay_1_low_%=:\n"
|
".delay_1_low_%=:\n"
|
||||||
"\tdec %[scratch]\n" // 1
|
"\tdec %[scratch]\n" // 1
|
||||||
"\tbrne .delay_1_low_%=\n" // exit: 1, loop: 2
|
"\tbrne .delay_1_low_%=\n" // exit: 1, loop: 2
|
||||||
"\tnop\n" // 1
|
"\tnop\n" // 1
|
||||||
"\tnop\n" // 1
|
"\tnop\n" // 1
|
||||||
// Rising edge
|
// Rising edge
|
||||||
"\tsts %[out_byte], %[line_high]\n" // 2
|
"\tsts %[out_byte], %[line_high]\n" // 2
|
||||||
// Wait for 2us (32 cycles) to sync with the bot_is_0 codepath.
|
// Wait for 2us (32 cycles) to sync with the bot_is_0 codepath.
|
||||||
// Time before: 0 cycles.
|
// Time before: 0 cycles.
|
||||||
// Time after: 2 cycles (rjmp).
|
// Time after: 2 cycles (rjmp).
|
||||||
// So 30 to go, so 10 3-cycles iterations and 0 nop.
|
// So 30 to go, so 10 3-cycles iterations and 0 nop.
|
||||||
"\tldi %[scratch], 10\n" // 1
|
"\tldi %[scratch], 10\n" // 1
|
||||||
".delay_1_high_%=:\n"
|
".delay_1_high_%=:\n"
|
||||||
"\tdec %[scratch]\n" // 1
|
"\tdec %[scratch]\n" // 1
|
||||||
"\tbrne .delay_1_high_%=\n" // exit: 1, loop: 2
|
"\tbrne .delay_1_high_%=\n" // exit: 1, loop: 2
|
||||||
"\trjmp .inner_common_path_%=\n" // 2
|
"\trjmp .inner_common_path_%=\n" // 2
|
||||||
|
|
||||||
".bit_is_0_%=:\n"
|
".bit_is_0_%=:\n"
|
||||||
// bit is a 0
|
// bit is a 0
|
||||||
// Stay high for 3us (48 cycles).
|
// Stay high for 3us (48 cycles).
|
||||||
// Time before: 4 cycles (mov, and, breq-true).
|
// Time before: 4 cycles (mov, and, breq-true).
|
||||||
// Time after: 2 cycles (sts).
|
// Time after: 2 cycles (sts).
|
||||||
// So 42 to go, so 14 3-cycles iterations, and 0 nop.
|
// So 42 to go, so 14 3-cycles iterations, and 0 nop.
|
||||||
"\tldi %[scratch], 14\n" // 1
|
"\tldi %[scratch], 14\n" // 1
|
||||||
".delay_0_low_%=:\n"
|
".delay_0_low_%=:\n"
|
||||||
"\tdec %[scratch]\n" // 1
|
"\tdec %[scratch]\n" // 1
|
||||||
"\tbrne .delay_0_low_%=\n" // exit: 1, loop: 2
|
"\tbrne .delay_0_low_%=\n" // exit: 1, loop: 2
|
||||||
// Rising edge
|
// Rising edge
|
||||||
"\tsts %[out_byte], %[line_high]\n" // 2
|
"\tsts %[out_byte], %[line_high]\n" // 2
|
||||||
|
|
||||||
// codepath common to both possible values
|
// codepath common to both possible values
|
||||||
".inner_common_path_%=:\n"
|
".inner_common_path_%=:\n"
|
||||||
"\tnop\n" // 1
|
"\tnop\n" // 1
|
||||||
"\tlsr %[mask]\n" // 1
|
"\tlsr %[mask]\n" // 1
|
||||||
"\tbreq .outer_loop_trailer_%=\n" // mask!=0: 1, mask==0: 2
|
"\tbreq .outer_loop_trailer_%=\n" // mask!=0: 1, mask==0: 2
|
||||||
// Stay high for 1us (16 cycles).
|
// Stay high for 1us (16 cycles).
|
||||||
// Time before: 3 cycles (nop, lsr, breq-false).
|
// Time before: 3 cycles (nop, lsr, breq-false).
|
||||||
// Time after: 4 cycles (rjmp, sts)
|
// Time after: 4 cycles (rjmp, sts)
|
||||||
// So 9 to go, so 3 3-cycles iterations and 0 nop.
|
// So 9 to go, so 3 3-cycles iterations and 0 nop.
|
||||||
"\tldi %[scratch], 3\n" // 1
|
"\tldi %[scratch], 3\n" // 1
|
||||||
".delay_common_high_%=:\n"
|
".delay_common_high_%=:\n"
|
||||||
"\tdec %[scratch]\n" // 1
|
"\tdec %[scratch]\n" // 1
|
||||||
"\tbrne .delay_common_high_%=\n" // exit: 1, loop: 2
|
"\tbrne .delay_common_high_%=\n" // exit: 1, loop: 2
|
||||||
"\trjmp .inner_loop_%=\n" // 2
|
"\trjmp .inner_loop_%=\n" // 2
|
||||||
|
|
||||||
".outer_loop_trailer_%=:\n"
|
".outer_loop_trailer_%=:\n"
|
||||||
"\tdec %[length]\n" // 1
|
"\tdec %[length]\n" // 1
|
||||||
"\tbreq .stop_bit_%=\n" // length!=0: 1, length==0: 2
|
"\tbreq .stop_bit_%=\n" // length!=0: 1, length==0: 2
|
||||||
// Stay high for 1us (16 cycles).
|
// Stay high for 1us (16 cycles).
|
||||||
// Time before: 6 cycles (lsr, nop, breq-true, dec, breq-false).
|
// Time before: 6 cycles (lsr, nop, breq-true, dec, breq-false).
|
||||||
// Time after: 7 cycles (rjmp, ldi, ld, sts).
|
// Time after: 7 cycles (rjmp, ldi, ld, sts).
|
||||||
// So 3 to go, so 3 nop (for simplicity).
|
// So 3 to go, so 3 nop (for simplicity).
|
||||||
"\tnop\n" // 1
|
"\tnop\n" // 1
|
||||||
"\tnop\n" // 1
|
"\tnop\n" // 1
|
||||||
"\tnop\n" // 1
|
"\tnop\n" // 1
|
||||||
"\trjmp .outer_loop_%=\n" // 2
|
"\trjmp .outer_loop_%=\n" // 2
|
||||||
// Done sending data, send a stop bit.
|
// Done sending data, send a stop bit.
|
||||||
".stop_bit_%=:\n"
|
".stop_bit_%=:\n"
|
||||||
// Stay high for 1us (16 cycles).
|
// Stay high for 1us (16 cycles).
|
||||||
// Time before: 7 cycles (lsr, nop, breq-true, dec, breq-true).
|
// Time before: 7 cycles (lsr, nop, breq-true, dec, breq-true).
|
||||||
// Time after: 2 cycles (sts).
|
// Time after: 2 cycles (sts).
|
||||||
// So 7 to go, so 2 3-cycles iterations and 1 nop.
|
// So 7 to go, so 2 3-cycles iterations and 1 nop.
|
||||||
"\tldi %[scratch], 2\n" // 1
|
"\tldi %[scratch], 2\n" // 1
|
||||||
".delay_stop_high_%=:\n"
|
".delay_stop_high_%=:\n"
|
||||||
"\tdec %[scratch]\n" // 1
|
"\tdec %[scratch]\n" // 1
|
||||||
"\tbrne .delay_stop_high_%=\n" // exit: 1, loop: 2
|
"\tbrne .delay_stop_high_%=\n" // exit: 1, loop: 2
|
||||||
"\tnop\n"
|
"\tnop\n"
|
||||||
"\tsts %[out_byte], %[line_low]\n" // 2
|
"\tsts %[out_byte], %[line_low]\n" // 2
|
||||||
// Stay low for 1us (16 cycles).
|
// Stay low for 1us (16 cycles).
|
||||||
// Time before: 0 cycles.
|
// Time before: 0 cycles.
|
||||||
// Time after: 2 cycles (sts).
|
// Time after: 2 cycles (sts).
|
||||||
// So 14 to go, so 4 3-cycles iterations and 2 nop.
|
// So 14 to go, so 4 3-cycles iterations and 2 nop.
|
||||||
"\tldi %[scratch], 5\n" // 1
|
"\tldi %[scratch], 5\n" // 1
|
||||||
".delay_stop_low_%=:\n"
|
".delay_stop_low_%=:\n"
|
||||||
"\tdec %[scratch]\n" // 1
|
"\tdec %[scratch]\n" // 1
|
||||||
"\tbrne .delay_stop_low_%=\n" // exit: 1, loop: 2
|
"\tbrne .delay_stop_low_%=\n" // exit: 1, loop: 2
|
||||||
"\tnop\n"
|
"\tnop\n"
|
||||||
"\tnop\n"
|
"\tnop\n"
|
||||||
"\tsts %[out_byte], %[line_high]\n" // 2
|
"\tsts %[out_byte], %[line_high]\n" // 2
|
||||||
// Notes on arguments:
|
// Notes on arguments:
|
||||||
// - mask and scratch are used wth "ldi", which can only work on registers
|
// - mask and scratch are used wth "ldi", which can only work on registers
|
||||||
// 16 to 31, so tag these with "a" rather than the generic "r"
|
// 16 to 31, so tag these with "a" rather than the generic "r"
|
||||||
// - mark all output-only arguments as early-clobber ("&"), as input
|
// - mark all output-only arguments as early-clobber ("&"), as input
|
||||||
// registers are used throughout all iterations and both sets must be
|
// registers are used throughout all iterations and both sets must be
|
||||||
// strictly distinct
|
// strictly distinct
|
||||||
// - tag buffer with "z", to use the "ld r?, Z+" instruction (load from
|
// - tag buffer with "z", to use the "ld r?, Z+" instruction (load from
|
||||||
// 16bits RAM address and postincrement, in 2 cycles).
|
// 16bits RAM address and postincrement, in 2 cycles).
|
||||||
// XXX: any pointer register pair would do, but mapping to Z explicitly
|
// XXX: any pointer register pair would do, but mapping to Z explicitly
|
||||||
// because I cannot find a way to get one of "X", "Y" or "Z" to appear
|
// because I cannot find a way to get one of "X", "Y" or "Z" to appear
|
||||||
// when expanding "%[buffer]", causing the assembler to reject the
|
// when expanding "%[buffer]", causing the assembler to reject the
|
||||||
// instruction. Pick Z as it is the only call-used such register,
|
// instruction. Pick Z as it is the only call-used such register,
|
||||||
// avoiding the need to preserve any value a caller may have set it to.
|
// avoiding the need to preserve any value a caller may have set it to.
|
||||||
: [buffer] "+z" (buffer),
|
: [buffer] "+z"(buffer),
|
||||||
[length] "+r" (length),
|
[length] "+r"(length),
|
||||||
[cur_byte] "=&r" (cur_byte),
|
[cur_byte] "=&r"(cur_byte),
|
||||||
[mask] "=&a" (mask),
|
[mask] "=&a"(mask),
|
||||||
[scratch] "=&a" (scratch)
|
[scratch] "=&a"(scratch)
|
||||||
: [line_low] "r" (line_low),
|
: [line_low] "r"(line_low),
|
||||||
[line_high] "r" (line_high),
|
[line_high] "r"(line_high),
|
||||||
[out_byte] "i" (&DDRH)
|
[out_byte] "i"(&DDRH)
|
||||||
: "cc", "memory"
|
: "cc", "memory");
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
word recvJoyBus(byte *output, byte byte_count) {
|
word recvJoyBus(byte* output, byte byte_count) {
|
||||||
// listen for expected byte_count bytes of data back from the controller
|
// listen for expected byte_count bytes of data back from the controller
|
||||||
// return the number of bytes not (fully) received if the delay for a signal
|
// return the number of bytes not (fully) received if the delay for a signal
|
||||||
// edge takes too long.
|
// edge takes too long.
|
||||||
@ -829,84 +828,83 @@ word recvJoyBus(byte *output, byte byte_count) {
|
|||||||
|
|
||||||
byte mask, cur_byte, timeout, scratch;
|
byte mask, cur_byte, timeout, scratch;
|
||||||
__asm__ __volatile__("\n"
|
__asm__ __volatile__("\n"
|
||||||
"\tldi %[mask], 0x80\n"
|
"\tldi %[mask], 0x80\n"
|
||||||
"\tclr %[cur_byte]\n"
|
"\tclr %[cur_byte]\n"
|
||||||
".read_loop_%=:\n"
|
".read_loop_%=:\n"
|
||||||
// Wait for input to be low. Time out if it takes more than ~27us (~7 bits
|
// Wait for input to be low. Time out if it takes more than ~27us (~7 bits
|
||||||
// worth of time) for it to go low.
|
// worth of time) for it to go low.
|
||||||
// Takes 5 cycles to exit on input-low iteration (lds, sbrs-false, rjmp).
|
// Takes 5 cycles to exit on input-low iteration (lds, sbrs-false, rjmp).
|
||||||
// Takes 7 cycles to loop on input-high iteration (lds, sbrs-true, dec,
|
// Takes 7 cycles to loop on input-high iteration (lds, sbrs-true, dec,
|
||||||
// brne-true).
|
// brne-true).
|
||||||
"\tldi %[timeout], 0x3f\n" // 1
|
"\tldi %[timeout], 0x3f\n" // 1
|
||||||
".read_wait_falling_edge_%=:\n"
|
".read_wait_falling_edge_%=:\n"
|
||||||
"\tlds %[scratch], %[in_byte]\n" // 2
|
"\tlds %[scratch], %[in_byte]\n" // 2
|
||||||
"\tsbrs %[scratch], %[in_bit]\n" // low: 1, high: 2
|
"\tsbrs %[scratch], %[in_bit]\n" // low: 1, high: 2
|
||||||
"\trjmp .read_input_low_%=\n" // 2
|
"\trjmp .read_input_low_%=\n" // 2
|
||||||
"\tdec %[timeout]\n" // 1
|
"\tdec %[timeout]\n" // 1
|
||||||
"\tbrne .read_wait_falling_edge_%=\n" // timeout==0: 1, timeout!=0: 2
|
"\tbrne .read_wait_falling_edge_%=\n" // timeout==0: 1, timeout!=0: 2
|
||||||
"\trjmp .read_end_%=\n" // 2
|
"\trjmp .read_end_%=\n" // 2
|
||||||
|
|
||||||
".read_input_low_%=:\n"
|
".read_input_low_%=:\n"
|
||||||
// Wait for 1500 us (24 cycles) before reading input.
|
// Wait for 1500 us (24 cycles) before reading input.
|
||||||
// As it takes from 5 to 7 cycles for the prevous loop to exit,
|
// As it takes from 5 to 7 cycles for the prevous loop to exit,
|
||||||
// this means this loop exits from 1812.5us to 1937.5us after the falling
|
// this means this loop exits from 1812.5us to 1937.5us after the falling
|
||||||
// edge, so at least 812.5us after a 1-bit rising edge, and at least
|
// edge, so at least 812.5us after a 1-bit rising edge, and at least
|
||||||
// 1062.5us before a 0-bit rising edge.
|
// 1062.5us before a 0-bit rising edge.
|
||||||
// This also leaves us with up to 2062.5us (33 cycles) to update cur_byte,
|
// This also leaves us with up to 2062.5us (33 cycles) to update cur_byte,
|
||||||
// possibly moving on to the next byte, waiting for a high input, and
|
// possibly moving on to the next byte, waiting for a high input, and
|
||||||
// waiting for the next falling edge.
|
// waiting for the next falling edge.
|
||||||
// Time taken until waiting for input high for non-last byte:
|
// Time taken until waiting for input high for non-last byte:
|
||||||
// - shift to current byte:
|
// - shift to current byte:
|
||||||
// - 1: 4 cycles (lds, sbrc-false, or)
|
// - 1: 4 cycles (lds, sbrc-false, or)
|
||||||
// - 0: 4 cycles (lds, sbrc-true)
|
// - 0: 4 cycles (lds, sbrc-true)
|
||||||
// - byte done: 8 cycles (lsr, brne-false, st, dec, brne-false, ldi, clr)
|
// - byte done: 8 cycles (lsr, brne-false, st, dec, brne-false, ldi, clr)
|
||||||
// - byte not done: 3 cycles (lsr, brne-true)
|
// - byte not done: 3 cycles (lsr, brne-true)
|
||||||
// Total: 7 to 12 cycles, so there are at least 21 cycles left until the
|
// Total: 7 to 12 cycles, so there are at least 21 cycles left until the
|
||||||
// next bit.
|
// next bit.
|
||||||
"\tldi %[timeout], 8\n" // 1
|
"\tldi %[timeout], 8\n" // 1
|
||||||
".read_wait_low_%=:\n"
|
".read_wait_low_%=:\n"
|
||||||
"\tdec %[timeout]\n" // 1
|
"\tdec %[timeout]\n" // 1
|
||||||
"\tbrne .read_wait_low_%=\n" // timeout=0: 1, timeout!=0: 2
|
"\tbrne .read_wait_low_%=\n" // timeout=0: 1, timeout!=0: 2
|
||||||
|
|
||||||
// Sample input
|
// Sample input
|
||||||
"\tlds %[scratch], %[in_byte]\n" // 2
|
"\tlds %[scratch], %[in_byte]\n" // 2
|
||||||
// Add to cur_byte
|
// Add to cur_byte
|
||||||
"\tsbrc %[scratch], %[in_bit]\n" // high: 1, low: 2
|
"\tsbrc %[scratch], %[in_bit]\n" // high: 1, low: 2
|
||||||
"\tor %[cur_byte], %[mask]\n" // 1
|
"\tor %[cur_byte], %[mask]\n" // 1
|
||||||
// Shift mask
|
// Shift mask
|
||||||
"\tlsr %[mask]\n"
|
"\tlsr %[mask]\n"
|
||||||
"\tbrne .read_wait_input_high_init_%=\n" // mask==0: 1, mask!=0: 2
|
"\tbrne .read_wait_input_high_init_%=\n" // mask==0: 1, mask!=0: 2
|
||||||
// A wole byte was read, store in output
|
// A wole byte was read, store in output
|
||||||
"\tst Z+, %[cur_byte]\n" // 2
|
"\tst Z+, %[cur_byte]\n" // 2
|
||||||
// Decrement byte count
|
// Decrement byte count
|
||||||
"\tdec %[byte_count]\n" // 1
|
"\tdec %[byte_count]\n" // 1
|
||||||
// Are we done reading ?
|
// Are we done reading ?
|
||||||
"\tbreq .read_end_%=\n" // byte_count!=0: 1, byte_count==0: 2
|
"\tbreq .read_end_%=\n" // byte_count!=0: 1, byte_count==0: 2
|
||||||
// No, prepare for reading another
|
// No, prepare for reading another
|
||||||
"\tldi %[mask], 0x80\n"
|
"\tldi %[mask], 0x80\n"
|
||||||
"\tclr %[cur_byte]\n"
|
"\tclr %[cur_byte]\n"
|
||||||
|
|
||||||
// Wait for rising edge
|
// Wait for rising edge
|
||||||
".read_wait_input_high_init_%=:"
|
".read_wait_input_high_init_%=:"
|
||||||
"\tldi %[timeout], 0x3f\n" // 1
|
"\tldi %[timeout], 0x3f\n" // 1
|
||||||
".read_wait_input_high_%=:\n"
|
".read_wait_input_high_%=:\n"
|
||||||
"\tlds %[scratch], %[in_byte]\n" // 2
|
"\tlds %[scratch], %[in_byte]\n" // 2
|
||||||
"\tsbrc %[scratch], %[in_bit]\n" // high: 1, low: 2
|
"\tsbrc %[scratch], %[in_bit]\n" // high: 1, low: 2
|
||||||
"\trjmp .read_loop_%=\n" // 2
|
"\trjmp .read_loop_%=\n" // 2
|
||||||
"\tdec %[timeout]\n" // 1
|
"\tdec %[timeout]\n" // 1
|
||||||
"\tbrne .read_wait_input_high_%=\n" // timeout==0: 1, timeout!=0: 2
|
"\tbrne .read_wait_input_high_%=\n" // timeout==0: 1, timeout!=0: 2
|
||||||
"\trjmp .read_end_%=\n" // 2
|
"\trjmp .read_end_%=\n" // 2
|
||||||
".read_end_%=:\n"
|
".read_end_%=:\n"
|
||||||
: [output] "+z" (output),
|
: [output] "+z"(output),
|
||||||
[byte_count] "+r" (byte_count),
|
[byte_count] "+r"(byte_count),
|
||||||
[mask] "=&a" (mask),
|
[mask] "=&a"(mask),
|
||||||
[cur_byte] "=&r" (cur_byte),
|
[cur_byte] "=&r"(cur_byte),
|
||||||
[timeout] "=&a" (timeout),
|
[timeout] "=&a"(timeout),
|
||||||
[scratch] "=&a" (scratch)
|
[scratch] "=&a"(scratch)
|
||||||
: [in_byte] "i" (&PINH),
|
: [in_byte] "i"(&PINH),
|
||||||
[in_bit] "i" (4)
|
[in_bit] "i"(4)
|
||||||
: "cc", "memory"
|
: "cc", "memory");
|
||||||
);
|
|
||||||
return byte_count;
|
return byte_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1528,11 +1526,11 @@ void checkController() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// read 32bytes from controller pak and calculate CRC
|
// read 32bytes from controller pak and calculate CRC
|
||||||
byte readBlock(byte *output, word myAddress) {
|
byte readBlock(byte* output, word myAddress) {
|
||||||
byte response_crc;
|
byte response_crc;
|
||||||
// Calculate the address CRC
|
// Calculate the address CRC
|
||||||
word myAddressCRC = addrCRC(myAddress);
|
word myAddressCRC = addrCRC(myAddress);
|
||||||
const byte command[] = { 0x02, (byte) (myAddressCRC >> 8), (byte) (myAddressCRC & 0xff) };
|
const byte command[] = { 0x02, (byte)(myAddressCRC >> 8), (byte)(myAddressCRC & 0xff) };
|
||||||
word error;
|
word error;
|
||||||
|
|
||||||
// don't want interrupts getting in the way
|
// don't want interrupts getting in the way
|
||||||
@ -1798,8 +1796,8 @@ void writeMPK() {
|
|||||||
myFile.read(command + 3, sizeof(command) - 3);
|
myFile.read(command + 3, sizeof(command) - 3);
|
||||||
|
|
||||||
word address_with_crc = addrCRC(address);
|
word address_with_crc = addrCRC(address);
|
||||||
command[1] = (byte) (address_with_crc >> 8);
|
command[1] = (byte)(address_with_crc >> 8);
|
||||||
command[2] = (byte) (address_with_crc & 0xff);
|
command[2] = (byte)(address_with_crc & 0xff);
|
||||||
|
|
||||||
// don't want interrupts getting in the way
|
// don't want interrupts getting in the way
|
||||||
noInterrupts();
|
noInterrupts();
|
||||||
@ -2191,7 +2189,7 @@ void writeEeprom() {
|
|||||||
// Blink led
|
// Blink led
|
||||||
blinkLED();
|
blinkLED();
|
||||||
if (page)
|
if (page)
|
||||||
delay(50); // Wait 50ms between pages when writing
|
delay(50); // Wait 50ms between pages when writing
|
||||||
|
|
||||||
noInterrupts();
|
noInterrupts();
|
||||||
sendJoyBus(command, sizeof(command));
|
sendJoyBus(command, sizeof(command));
|
||||||
@ -2211,7 +2209,7 @@ void writeEeprom() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void readEepromPageList(byte *output, byte page_number, byte page_count) {
|
void readEepromPageList(byte* output, byte page_number, byte page_count) {
|
||||||
byte command[] = { 0x04, page_number };
|
byte command[] = { 0x04, page_number };
|
||||||
|
|
||||||
// Disable interrupts for more uniform clock pulses
|
// Disable interrupts for more uniform clock pulses
|
||||||
@ -2226,7 +2224,7 @@ void readEepromPageList(byte *output, byte page_number, byte page_count) {
|
|||||||
interrupts();
|
interrupts();
|
||||||
|
|
||||||
if (page_count)
|
if (page_count)
|
||||||
delayMicroseconds(600); // wait 600us between pages when reading
|
delayMicroseconds(600); // wait 600us between pages when reading
|
||||||
|
|
||||||
command[1]++;
|
command[1]++;
|
||||||
output += 8;
|
output += 8;
|
||||||
|
@ -1068,7 +1068,7 @@ void CreateROMFolderInSD() {
|
|||||||
sd.chdir(folder);
|
sd.chdir(folder);
|
||||||
}
|
}
|
||||||
|
|
||||||
FsFile createNewFile(const char *prefix, const char *extension) {
|
FsFile createNewFile(const char* prefix, const char* extension) {
|
||||||
char filename[FILENAME_LENGTH];
|
char filename[FILENAME_LENGTH];
|
||||||
snprintf_P(filename, sizeof(filename), _file_name_no_number_fmt, prefix, extension);
|
snprintf_P(filename, sizeof(filename), _file_name_no_number_fmt, prefix, extension);
|
||||||
for (byte i = 0; i < 100; i++) {
|
for (byte i = 0; i < 100; i++) {
|
||||||
|
@ -893,7 +893,7 @@ void readROM_SFM() {
|
|||||||
|
|
||||||
//clear the screen
|
//clear the screen
|
||||||
display_Clear();
|
display_Clear();
|
||||||
println_Msg(F("Creating folder: "));
|
print_Msg(F("Creating folder "));
|
||||||
println_Msg(folder);
|
println_Msg(folder);
|
||||||
display_Update();
|
display_Update();
|
||||||
|
|
||||||
@ -927,7 +927,7 @@ void readROM_SFM() {
|
|||||||
println_Msg(F("Dumping HiRom..."));
|
println_Msg(F("Dumping HiRom..."));
|
||||||
display_Update();
|
display_Update();
|
||||||
|
|
||||||
for (byte currBank = 192; currBank < (numBanks + 192); currBank++) {
|
for (word currBank = 192; currBank < (numBanks + 192); currBank++) {
|
||||||
for (long currByte = 0; currByte < 65536; currByte += 512) {
|
for (long currByte = 0; currByte < 65536; currByte += 512) {
|
||||||
for (int c = 0; c < 512; c++) {
|
for (int c = 0; c < 512; c++) {
|
||||||
sdBuffer[c] = readBank_SFM(currBank, currByte + c);
|
sdBuffer[c] = readBank_SFM(currBank, currByte + c);
|
||||||
@ -1009,8 +1009,7 @@ void idFlash_SFM(int startBank) {
|
|||||||
void writeFlash_SFM(int startBank, uint32_t pos) {
|
void writeFlash_SFM(int startBank, uint32_t pos) {
|
||||||
display_Clear();
|
display_Clear();
|
||||||
print_Msg(F("Writing Bank 0x"));
|
print_Msg(F("Writing Bank 0x"));
|
||||||
print_Msg(startBank, HEX);
|
println_Msg(startBank, HEX);
|
||||||
print_Msg(F("..."));
|
|
||||||
display_Update();
|
display_Update();
|
||||||
|
|
||||||
// Open file on sd card
|
// Open file on sd card
|
||||||
@ -1026,8 +1025,13 @@ void writeFlash_SFM(int startBank, uint32_t pos) {
|
|||||||
dataOut();
|
dataOut();
|
||||||
|
|
||||||
if (romType) {
|
if (romType) {
|
||||||
|
//Initialize progress bar
|
||||||
|
uint32_t processedProgressBar = 0;
|
||||||
|
uint32_t totalProgressBar = numBanks * 0x10000;
|
||||||
|
draw_progressbar(0, totalProgressBar);
|
||||||
|
|
||||||
// Write hirom
|
// Write hirom
|
||||||
for (byte currBank = startBank; currBank < startBank + numBanks; currBank++) {
|
for (word currBank = startBank; currBank < startBank + numBanks; currBank++) {
|
||||||
// Fill SDBuffer with 1 page at a time then write it repeat until all bytes are written
|
// Fill SDBuffer with 1 page at a time then write it repeat until all bytes are written
|
||||||
for (unsigned long currByte = 0; currByte < 0x10000; currByte += 128) {
|
for (unsigned long currByte = 0; currByte < 0x10000; currByte += 128) {
|
||||||
myFile.read(sdBuffer, 128);
|
myFile.read(sdBuffer, 128);
|
||||||
@ -1049,8 +1053,16 @@ void writeFlash_SFM(int startBank, uint32_t pos) {
|
|||||||
// Wait until write is finished
|
// Wait until write is finished
|
||||||
busyCheck_SFM(startBank);
|
busyCheck_SFM(startBank);
|
||||||
}
|
}
|
||||||
|
// update progress bar
|
||||||
|
processedProgressBar += 0x10000;
|
||||||
|
draw_progressbar(processedProgressBar, totalProgressBar);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
//Initialize progress bar
|
||||||
|
uint32_t processedProgressBar = 0;
|
||||||
|
uint32_t totalProgressBar = numBanks * 0x8000;
|
||||||
|
draw_progressbar(0, totalProgressBar);
|
||||||
|
|
||||||
// Write lorom
|
// Write lorom
|
||||||
for (byte currBank = 0; currBank < numBanks; currBank++) {
|
for (byte currBank = 0; currBank < numBanks; currBank++) {
|
||||||
for (unsigned long currByte = 0x8000; currByte < 0x10000; currByte += 128) {
|
for (unsigned long currByte = 0x8000; currByte < 0x10000; currByte += 128) {
|
||||||
@ -1072,6 +1084,9 @@ void writeFlash_SFM(int startBank, uint32_t pos) {
|
|||||||
// Wait until write is finished
|
// Wait until write is finished
|
||||||
busyCheck_SFM(startBank);
|
busyCheck_SFM(startBank);
|
||||||
}
|
}
|
||||||
|
// update progress bar
|
||||||
|
processedProgressBar += 0x8000;
|
||||||
|
draw_progressbar(processedProgressBar, totalProgressBar);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Close the file:
|
// Close the file:
|
||||||
@ -1155,7 +1170,7 @@ byte blankcheck_SFM(int startBank) {
|
|||||||
|
|
||||||
byte blank = 1;
|
byte blank = 1;
|
||||||
if (romType) {
|
if (romType) {
|
||||||
for (byte currBank = startBank; currBank < startBank + numBanks; currBank++) {
|
for (word currBank = startBank; currBank < startBank + numBanks; currBank++) {
|
||||||
for (unsigned long currByte = 0; currByte < 0x10000; currByte++) {
|
for (unsigned long currByte = 0; currByte < 0x10000; currByte++) {
|
||||||
if (readBank_SFM(currBank, currByte) != 0xFF) {
|
if (readBank_SFM(currBank, currByte) != 0xFF) {
|
||||||
currBank = startBank + numBanks;
|
currBank = startBank + numBanks;
|
||||||
@ -1192,7 +1207,7 @@ unsigned long verifyFlash_SFM(int startBank, uint32_t pos) {
|
|||||||
controlIn_SFM();
|
controlIn_SFM();
|
||||||
|
|
||||||
if (romType) {
|
if (romType) {
|
||||||
for (byte currBank = startBank; currBank < startBank + numBanks; currBank++) {
|
for (word currBank = startBank; currBank < startBank + numBanks; currBank++) {
|
||||||
for (unsigned long currByte = 0; currByte < 0x10000; currByte += 512) {
|
for (unsigned long currByte = 0; currByte < 0x10000; currByte += 512) {
|
||||||
// Fill SDBuffer
|
// Fill SDBuffer
|
||||||
myFile.read(sdBuffer, 512);
|
myFile.read(sdBuffer, 512);
|
||||||
@ -1244,7 +1259,7 @@ void readFlash_SFM() {
|
|||||||
print_FatalError(create_file_STR);
|
print_FatalError(create_file_STR);
|
||||||
}
|
}
|
||||||
if (romType) {
|
if (romType) {
|
||||||
for (byte currBank = 0xC0; currBank < 0xC0 + numBanks; currBank++) {
|
for (word currBank = 0xC0; currBank < 0xC0 + numBanks; currBank++) {
|
||||||
for (unsigned long currByte = 0; currByte < 0x10000; currByte += 512) {
|
for (unsigned long currByte = 0; currByte < 0x10000; currByte += 512) {
|
||||||
for (int c = 0; c < 512; c++) {
|
for (int c = 0; c < 512; c++) {
|
||||||
sdBuffer[c] = readBank_SFM(currBank, currByte + c);
|
sdBuffer[c] = readBank_SFM(currBank, currByte + c);
|
||||||
|
@ -602,7 +602,7 @@ void readLoRomBanks(unsigned int start, unsigned int total, FsFile* file) {
|
|||||||
uint32_t totalProgressBar = (uint32_t)(total - start) * 1024;
|
uint32_t totalProgressBar = (uint32_t)(total - start) * 1024;
|
||||||
draw_progressbar(0, totalProgressBar);
|
draw_progressbar(0, totalProgressBar);
|
||||||
|
|
||||||
for (byte currBank = start; currBank < total; currBank++) {
|
for (word currBank = start; currBank < total; currBank++) {
|
||||||
PORTL = currBank;
|
PORTL = currBank;
|
||||||
|
|
||||||
// Blink led
|
// Blink led
|
||||||
@ -653,7 +653,7 @@ void readHiRomBanks(unsigned int start, unsigned int total, FsFile* file) {
|
|||||||
uint32_t totalProgressBar = (uint32_t)(total - start) * 1024;
|
uint32_t totalProgressBar = (uint32_t)(total - start) * 1024;
|
||||||
draw_progressbar(0, totalProgressBar);
|
draw_progressbar(0, totalProgressBar);
|
||||||
|
|
||||||
for (byte currBank = start; currBank < total; currBank++) {
|
for (word currBank = start; currBank < total; currBank++) {
|
||||||
PORTL = currBank;
|
PORTL = currBank;
|
||||||
|
|
||||||
// Blink led
|
// Blink led
|
||||||
|
Loading…
x
Reference in New Issue
Block a user