Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/ClusterM/famicom-dumper.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCluster <clusterrr@clusterrr.com>2020-09-02 20:42:49 +0300
committerCluster <clusterrr@clusterrr.com>2020-09-02 20:42:49 +0300
commit163fdc7d320b15ee03e66cbb13a036e857fe9207 (patch)
tree23f6b0810f28bb1c4c8d51e05e2f24ddbee3f131
parent219ee887a94b8886ba0e630358f3303c218707a6 (diff)
New protocol version
-rw-r--r--comm.c4
-rw-r--r--comm.h40
-rw-r--r--defines.h4
-rw-r--r--dumper.c475
-rw-r--r--famicom-dumper.hex513
5 files changed, 404 insertions, 632 deletions
diff --git a/comm.c b/comm.c
index ae676b4..36ca781 100644
--- a/comm.c
+++ b/comm.c
@@ -14,7 +14,7 @@ static uint8_t comm_recv_error;
volatile uint8_t comm_recv_command;
volatile unsigned int comm_recv_length;
-volatile uint8_t recv_buffer[RECV_BUFFER];
+volatile uint8_t recv_buffer[RECV_BUFFER+8];
volatile uint8_t comm_recv_done;
static void comm_calc_send_crc(uint8_t inbyte)
@@ -105,7 +105,7 @@ void comm_proceed(uint8_t data)
comm_recv_length |= (uint16_t)data << 8;
break;
default:
- if (l >= RECV_BUFFER)
+ if (l >= sizeof(recv_buffer))
{
comm_recv_pos = 0;
comm_recv_error = 1;
diff --git a/comm.h b/comm.h
index 387e63f..551a593 100644
--- a/comm.h
+++ b/comm.h
@@ -15,32 +15,36 @@
#define COMMAND_CHR_READ_RESULT 12
#define COMMAND_CHR_WRITE_REQUEST 13
#define COMMAND_CHR_WRITE_DONE 14
-#define COMMAND_PHI2_INIT 15
-#define COMMAND_PHI2_INIT_DONE 16
+//#define COMMAND_PHI2_INIT 15
+//#define COMMAND_PHI2_INIT_DONE 16
#define COMMAND_MIRRORING_REQUEST 17
#define COMMAND_MIRRORING_RESULT 18
#define COMMAND_RESET 19
#define COMMAND_RESET_ACK 20
-#define COMMAND_PRG_EPROM_WRITE_REQUEST 21
-#define COMMAND_CHR_EPROM_WRITE_REQUEST 22
-#define COMMAND_EPROM_PREPARE 23
-#define COMMAND_PRG_FLASH_ERASE_REQUEST 24
-#define COMMAND_PRG_FLASH_WRITE_REQUEST 25
-#define COMMAND_CHR_FLASH_ERASE_REQUEST 26
-#define COMMAND_CHR_FLASH_WRITE_REQUEST 27
-#define COMMAND_JTAG_SETUP 28
-#define COMMAND_JTAG_SHUTDOWN 29
-#define COMMAND_JTAG_EXECUTE 30
-#define COMMAND_JTAG_RESULT 31
-#define COMMAND_TEST_SET 32
-#define COMMAND_TEST_RESULT 33
+//#define COMMAND_PRG_EPROM_WRITE_REQUEST 21
+//#define COMMAND_CHR_EPROM_WRITE_REQUEST 22
+//#define COMMAND_EPROM_PREPARE 23
+//#define COMMAND_PRG_FLASH_ERASE_REQUEST 24
+//#define COMMAND_PRG_FLASH_WRITE_REQUEST 25
+//#define COMMAND_CHR_FLASH_ERASE_REQUEST 26
+//#define COMMAND_CHR_FLASH_WRITE_REQUEST 27
+//#define COMMAND_JTAG_SETUP 28
+//#define COMMAND_JTAG_SHUTDOWN 29
+//#define COMMAND_JTAG_EXECUTE 30
+//#define COMMAND_JTAG_RESULT 31
+//#define COMMAND_TEST_SET 32
+//#define COMMAND_TEST_RESULT 33
#define COMMAND_COOLBOY_READ_REQUEST 34
#define COMMAND_COOLBOY_ERASE_REQUEST 35
#define COMMAND_COOLBOY_WRITE_REQUEST 36
-#define COMMAND_COOLGIRL_ERASE_SECTOR_REQUEST 37
-#define COMMAND_COOLGIRL_WRITE_REQUEST 38
+#define COMMAND_FLASH_ERASE_SECTOR_REQUEST 37
+#define COMMAND_FLASH_WRITE_REQUEST 38
#define COMMAND_PRG_CRC_READ_REQUEST 39
#define COMMAND_CHR_CRC_READ_REQUEST 40
+#define COMMAND_FLASH_WRITE_ERROR 41
+#define COMMAND_FLASH_WRITE_TIMEOUT 42
+#define COMMAND_FLASH_ERASE_ERROR 43
+#define COMMAND_FLASH_ERASE_TIMEOUT 44
#define COMMAND_BOOTLOADER 0xFE
#define COMMAND_DEBUG 0xFF
@@ -52,5 +56,5 @@ void comm_proceed(uint8_t data);
extern volatile uint8_t comm_recv_command;
extern volatile unsigned int comm_recv_length;
-extern volatile uint8_t recv_buffer[RECV_BUFFER];
+extern volatile uint8_t recv_buffer[RECV_BUFFER+8];
extern volatile uint8_t comm_recv_done;
diff --git a/defines.h b/defines.h
index ada87b0..220c235 100644
--- a/defines.h
+++ b/defines.h
@@ -3,7 +3,9 @@
#define F_CPU 8000000UL
#define UART_BAUD 250000UL
-#define RECV_BUFFER 1050
+#define RECV_BUFFER 2048
+#define SEND_BUFFER 32768
+#define PROTOCOL_VERSION 2
#define COOLBOY_GPIO_PORT B
#define COOLBOY_RD_PIN 4
diff --git a/dumper.c b/dumper.c
index 40dd0a2..5c8430f 100644
--- a/dumper.c
+++ b/dumper.c
@@ -60,18 +60,6 @@ ISR(USART0_RX_vect)
}
}
-static void phi2_init()
-{
- int i = 0x80;
- unsigned char h = PORTF |= (1<<0);
- unsigned char l = PORTF &= ~(1<<0);
- while(i != 0){
- PORTA = l;
- PORTA = h;
- i--;
- }
-}
-
static void set_address(unsigned int address)
{
unsigned char l = address & 0xFF;
@@ -104,12 +92,11 @@ static unsigned char read_prg_byte(unsigned int address)
MODE_READ;
PRG_READ;
set_address(address);
- //_delay_us(1);
-
PHI2_HI;
set_romsel(address); // set /ROMSEL high if need
_delay_us(1);
uint8_t result = PIND;
+ ROMSEL_HI;
return result;
}
@@ -119,11 +106,8 @@ static unsigned char read_chr_byte(unsigned int address)
ROMSEL_HI;
MODE_READ;
set_address(address);
- //_delay_us(1);
-
CHR_READ_LOW;
_delay_us(1);
-
uint8_t result = PIND;
CHR_READ_HI;
PHI2_HI;
@@ -132,6 +116,8 @@ static unsigned char read_chr_byte(unsigned int address)
static unsigned char read_coolboy_byte(unsigned int address)
{
+ PHI2_LOW;
+ ROMSEL_HI;
MODE_READ;
PRG_READ;
set_address(address);
@@ -140,7 +126,10 @@ static unsigned char read_coolboy_byte(unsigned int address)
COOLBOY_PORT |= 1<<COOLBOY_WR_PIN;
COOLBOY_PORT &= ~(1<<COOLBOY_RD_PIN);
_delay_us(1);
- return PIND;
+ uint8_t result = PIND;
+ ROMSEL_HI;
+ COOLBOY_PORT |= 1<<COOLBOY_RD_PIN;
+ return result;
}
static void read_prg_send(unsigned int address, unsigned int len)
@@ -154,8 +143,6 @@ static void read_prg_send(unsigned int address, unsigned int len)
address++;
}
set_address(0);
- PHI2_HI;
- ROMSEL_HI;
LED_GREEN_OFF;
}
@@ -170,8 +157,6 @@ static void read_chr_send(unsigned int address, unsigned int len)
address++;
}
set_address(0);
- PHI2_HI;
- ROMSEL_HI;
LED_GREEN_OFF;
}
@@ -193,21 +178,13 @@ static void read_prg_crc_send(unsigned int address, unsigned int len)
{
LED_GREEN_ON;
uint16_t crc = 0;
- read_prg_byte(address);
while (len > 0)
{
- unsigned char l = address & 0xFF;
- unsigned char h = address>>8;
- PORTA = l;
- PORTC = h;
- _delay_us(1);
- crc = crc16_update(crc, PIND);
+ crc = crc16_update(crc, read_prg_byte(address));
len--;
address++;
}
set_address(0);
- PHI2_HI;
- ROMSEL_HI;
comm_start(COMMAND_PRG_READ_RESULT, 2);
comm_send_byte(crc & 0xFF);
comm_send_byte((crc >> 8) & 0xFF);
@@ -225,8 +202,6 @@ static void read_chr_crc_send(unsigned int address, unsigned int len)
address++;
}
set_address(0);
- PHI2_HI;
- ROMSEL_HI;
comm_start(COMMAND_CHR_READ_RESULT, 2);
comm_send_byte(crc & 0xFF);
comm_send_byte((crc >> 8) & 0xFF);
@@ -337,6 +312,8 @@ static void write_prg_flash_command(unsigned int address, uint8_t data)
static void write_coolboy_flash_command(unsigned int address, uint8_t data)
{
+ COOLBOY_DDR |= 1<<COOLBOY_RD_PIN;
+ COOLBOY_DDR |= 1<<COOLBOY_WR_PIN;
COOLBOY_PORT |= 1<<COOLBOY_RD_PIN;
COOLBOY_PORT |= 1<<COOLBOY_WR_PIN;
ROMSEL_HI;
@@ -346,135 +323,62 @@ static void write_coolboy_flash_command(unsigned int address, uint8_t data)
PORTD = data;
PHI2_HI;
ROMSEL_LOW;
+ _delay_us(1);
+ COOLBOY_PORT &= ~(1<<COOLBOY_WR_PIN);
_delay_us(1);
-
- PORTB &= ~(1<<COOLBOY_WR_PIN);
-
- _delay_us(1);
-
- PORTB |= 1<<COOLBOY_WR_PIN;
+ COOLBOY_PORT |= 1<<COOLBOY_WR_PIN;
set_address(0);
ROMSEL_HI;
MODE_READ;
}
-static void write_chr_flash_command(unsigned int address, uint8_t data)
-{
- write_chr_byte(address, data);
-}
-
-static int write_prg_flash_byte(unsigned int address, uint8_t data)
-{
- write_prg_flash_command(0x0000, 0xF0);
- write_prg_flash_command(0x0555, 0xAA);
- write_prg_flash_command(0x02AA, 0x55);
- write_prg_flash_command(0x0555, 0xA0);
-
- write_prg_flash_command(address, data);
- _delay_us(50);
-
- int timeout = 0;
- uint8_t res, last_res = 0;
- while (timeout < 200)
- {
- res = read_prg_byte(address | 0x8000);
- ROMSEL_HI;
- if (res == last_res && last_res == data) break;
- last_res = res;
- _delay_us(50);
- timeout++;
- }
- //PHI2_LOW;
- ROMSEL_HI;
- set_address(0);
-
- return timeout < 10;
-}
-
-
-static int write_chr_flash_byte(unsigned int address, uint8_t data)
-{
- write_chr_flash_command(0x0000, 0xF0);
- write_chr_flash_command(0x0555, 0xAA);
- write_chr_flash_command(0x02AA, 0x55);
- write_chr_flash_command(0x0555, 0xA0);
- write_chr_flash_command(address, data);
-
- int timeout = 0;
- while (read_chr_byte(address | 0x8000) != data && timeout < 10)
- {
- _delay_us(100);
- timeout++;
- }
- set_address(0);
- PHI2_LOW;
- ROMSEL_HI;
-
- return timeout < 10;
-}
-
-static int erase_prg_flash()
-{
- LED_RED_ON;
- write_prg_flash_command(0x0000, 0xF0);
- write_prg_flash_command(0x0AAA, 0xAA);
- write_prg_flash_command(0x0555, 0x55);
- write_prg_flash_command(0x0AAA, 0x80);
- write_prg_flash_command(0x0AAA, 0xAA);
- write_prg_flash_command(0x0555, 0x55);
- write_prg_flash_command(0x0AAA, 0x10);
-
- int timeout = 0;
- while ((read_prg_byte(0x8000) != 0xFF) && (timeout < 300000))
- {
- _delay_ms(1);
- timeout++;
- }
- set_address(0);
- PHI2_HI;
- ROMSEL_HI;
-
- LED_RED_OFF;
- return timeout < 300000;
-}
-
-static int erase_coolboy_sector()
+static void erase_coolboy_sector()
{
LED_RED_ON;
- COOLBOY_PORT |= 1<<COOLBOY_RD_PIN;
- COOLBOY_PORT |= 1<<COOLBOY_WR_PIN;
- COOLBOY_DDR |= 1<<COOLBOY_RD_PIN;
- COOLBOY_DDR |= 1<<COOLBOY_WR_PIN;
- ROMSEL_HI;
-
write_coolboy_flash_command(0x0000, 0xF0);
write_coolboy_flash_command(0x0AAA, 0xAA);
write_coolboy_flash_command(0x0555, 0x55);
write_coolboy_flash_command(0x0AAA, 0x80);
write_coolboy_flash_command(0x0AAA, 0xAA);
write_coolboy_flash_command(0x0555, 0x55);
- write_coolboy_flash_command(0x0000, 0x30);
+ write_coolboy_flash_command(0x0000, 0x30);
- int timeout = 0;
- uint8_t debug;
- while (((debug = read_coolboy_byte(0x8000)) != 0xFF) && (timeout < 3000))
+ long int timeout = 0;
+ uint8_t res;
+ int16_t last_res = -1;
+ while (1)
{
- //comm_start(0xFF, 1);
- //comm_send_byte(debug);
- _delay_ms(1);
timeout++;
+ if (timeout >= 1000000)
+ {
+ // timeout
+ comm_start(COMMAND_FLASH_ERASE_TIMEOUT, 0);
+ break;
+ }
+ res = read_coolboy_byte(0x8000);
+ if ((last_res == -1) || ((res ^ (last_res & 0xFF)) & ((1 << 6) | (1 << 2))))
+ {
+ // in progress
+ last_res = res;
+ continue;
+ }
+ // done
+ if (res == 0xFF)
+ {
+ // ok
+ comm_start(COMMAND_PRG_WRITE_DONE, 0);
+ break;
+ } else {
+ // error
+ comm_start(COMMAND_FLASH_ERASE_ERROR, 1);
+ comm_send_byte(res);
+ break;
+ }
}
-
- set_address(0);
- ROMSEL_HI;
-
- COOLBOY_DDR &= ~((1<<COOLBOY_RD_PIN) | (1<<COOLBOY_RD_PIN));
- COOLBOY_PORT &= ~((1<<COOLBOY_RD_PIN) | (1<<COOLBOY_RD_PIN));
LED_RED_OFF;
- return timeout < 3000;
}
-static int erase_coolgirl_sector()
+static void erase_flash_sector()
{
LED_RED_ON;
write_prg_flash_command(0x0000, 0xF0);
@@ -485,90 +389,54 @@ static int erase_coolgirl_sector()
write_prg_flash_command(0x0555, 0x55);
write_prg_flash_command(0x0000, 0x30);
- int timeout = 0;
- uint8_t debug;
- while (((debug = read_prg_byte(0x8000)) != 0xFF) && (timeout < 3000))
- {
- ROMSEL_HI;
- //comm_start(0xFF, 1);
- //comm_send_byte(debug);
- _delay_ms(1);
- timeout++;
- }
- //comm_start(0xFF, 1);
- //comm_send_byte(debug);
- set_address(0);
- PHI2_HI;
- ROMSEL_HI;
-
- LED_RED_OFF;
- return timeout < 3000;
-}
-
-static int erase_chr_flash()
-{
- LED_RED_ON;
- write_chr_flash_command(0x0000, 0xF0);
- write_chr_flash_command(0x0555, 0xAA);
- write_chr_flash_command(0x02AA, 0x55);
- write_chr_flash_command(0x0555, 0x80);
- write_chr_flash_command(0x0555, 0xAA);
- write_chr_flash_command(0x02AA, 0x55);
- write_chr_flash_command(0x0555, 0x10);
-
- int timeout = 0;
- while ((read_chr_byte(0) != 0xFF) && (timeout < 10000))
+ long int timeout = 0;
+ uint8_t res;
+ int16_t last_res = -1;
+ while (1)
{
- _delay_ms(1);
timeout++;
- }
- set_address(0);
- PHI2_HI;
- ROMSEL_HI;
-
- LED_RED_OFF;
- return timeout < 10000;
-}
-
-static int write_prg_flash(unsigned int address, unsigned int len, uint8_t* data)
-{
- LED_RED_ON;
- int ok = 1;
- while (len > 0)
- {
- if (!write_prg_flash_byte(address, *data))
+ if (timeout >= 1000000)
{
- ok = 0;
+ // timeout
+ comm_start(COMMAND_FLASH_ERASE_TIMEOUT, 0);
break;
}
- address++;
- len--;
- data++;
+ res = read_prg_byte(0x8000);
+ if ((last_res == -1) || ((res != (last_res & 0xFF))))
+ {
+ // in progress
+ last_res = res;
+ continue;
+ }
+ // done
+ if (res == 0xFF)
+ {
+ // ok
+ comm_start(COMMAND_PRG_WRITE_DONE, 0);
+ break;
+ } else {
+ // error
+ comm_start(COMMAND_FLASH_ERASE_ERROR, 1);
+ comm_send_byte(res);
+ break;
+ }
}
LED_RED_OFF;
- return ok;
}
-static int write_coolboy(unsigned int address, unsigned int len, uint8_t* data)
+static void write_coolboy(unsigned int address, unsigned int len, uint8_t* data)
{
LED_RED_ON;
- COOLBOY_PORT |= 1<<COOLBOY_RD_PIN;
- COOLBOY_PORT |= 1<<COOLBOY_WR_PIN;
- COOLBOY_DDR |= 1<<COOLBOY_RD_PIN;
- COOLBOY_DDR |= 1<<COOLBOY_WR_PIN;
- ROMSEL_HI;
- uint8_t ok = 1;
while (len > 0)
{
-
- //uint8_t count = len > 16 ? 16 : len;
uint8_t count = 0;
uint8_t* d = data;
unsigned int a = address;
unsigned int address_base = a & 0xFFE0;
- while (len > 0 && ((a & 0xFFE0) == address_base))
+ while ((len > 0) && ((a & 0xFFE0) == address_base))
{
- if (*d != 0xFF) count++;
+ if (*d != 0xFF)
+ count++;
a++;
len--;
d++;
@@ -576,7 +444,7 @@ static int write_coolboy(unsigned int address, unsigned int len, uint8_t* data)
if (count)
{
- //write_prg_flash_command(0x0000, 0xF0);
+ write_coolboy_flash_command(0x0000, 0xF0);
write_coolboy_flash_command(0x0AAA, 0xAA);
write_coolboy_flash_command(0x0555, 0x55);
write_coolboy_flash_command(0x0000, 0x25);
@@ -594,50 +462,59 @@ static int write_coolboy(unsigned int address, unsigned int len, uint8_t* data)
}
write_coolboy_flash_command(0x0000, 0x29);
- _delay_us(10);
long int timeout = 0;
- uint8_t res, last_res = 0;
- while (timeout < 100000)
+ uint8_t res;
+ int16_t last_res = -1;
+ while (1)
{
- res = read_coolboy_byte((address-1) | 0x8000);
- ROMSEL_HI;
- if (res == last_res && last_res == *(data-1)) break;
- last_res = res;
- _delay_us(10);
timeout++;
- }
- if (timeout >= 100000)
- {
- ok = 0;
- break;
+ if (timeout >= 100000)
+ {
+ // timeout
+ comm_start(COMMAND_FLASH_WRITE_TIMEOUT, 0);
+ LED_RED_OFF;
+ return;
+ }
+ res = read_coolboy_byte((address-1) | 0x8000);
+ if ((last_res == -1) || ((res != (last_res & 0xFF))))
+ {
+ // in progress
+ last_res = res;
+ continue;
+ }
+ // done
+ if (res == *(data-1))
+ {
+ // ok
+ break;
+ } else {
+ // error
+ comm_start(COMMAND_FLASH_WRITE_ERROR, 1);
+ comm_send_byte(res);
+ LED_RED_OFF;
+ return;
+ }
}
}
-
+
address = a;
data = d;
}
- ROMSEL_HI;
- COOLBOY_DDR &= ~((1<<COOLBOY_RD_PIN) | (1<<COOLBOY_RD_PIN));
- COOLBOY_PORT &= ~((1<<COOLBOY_RD_PIN) | (1<<COOLBOY_RD_PIN));
+ comm_start(COMMAND_PRG_WRITE_DONE, 0);
LED_RED_OFF;
- return ok;
}
-static int write_coolgirl(unsigned int address, unsigned int len, uint8_t* data)
+static void write_flash(unsigned int address, unsigned int len, uint8_t* data)
{
LED_RED_ON;
- ROMSEL_HI;
- uint8_t ok = 1;
while (len > 0)
{
-
- //uint8_t count = len > 16 ? 16 : len;
uint8_t count = 0;
uint8_t* d = data;
unsigned int a = address;
unsigned int address_base = a & 0xFFE0;
- while (len > 0 && ((a & 0xFFE0) == address_base))
+ while ((len > 0) && ((a & 0xFFE0) == address_base))
{
if (*d != 0xFF)
count++;
@@ -666,56 +543,47 @@ static int write_coolgirl(unsigned int address, unsigned int len, uint8_t* data)
}
write_prg_flash_command(0x0000, 0x29);
- _delay_us(10);
long int timeout = 0;
- uint8_t res, last_res = 0;
- while (timeout < 100000)
+ uint8_t res;
+ int16_t last_res = -1;
+ while (1)
{
- res = read_prg_byte((address-1) | 0x8000);
- //comm_start(0xFF, 1);
- //comm_send_byte(res);
- ROMSEL_HI;
- if (res == last_res && last_res == *(data-1)) break;
- last_res = res;
- _delay_us(10);
timeout++;
- }
- //comm_start(0xFF, 1);
- //comm_send_byte(res);
- if (timeout >= 100000)
- {
- ok = 0;
- break;
+ if (timeout >= 100000)
+ {
+ // timeout
+ comm_start(COMMAND_FLASH_WRITE_TIMEOUT, 0);
+ LED_RED_OFF;
+ return;
+ }
+ res = read_prg_byte((address-1) | 0x8000);
+ if ((last_res == -1) || ((res != (last_res & 0xFF))))
+ {
+ // in progress
+ last_res = res;
+ continue;
+ }
+ // done
+ if (res == *(data-1))
+ {
+ // ok
+ break;
+ } else {
+ // error
+ comm_start(COMMAND_FLASH_WRITE_ERROR, 1);
+ comm_send_byte(res);
+ LED_RED_OFF;
+ return;
+ }
}
}
address = a;
data = d;
}
- ROMSEL_HI;
+ comm_start(COMMAND_PRG_WRITE_DONE, 0);
LED_RED_OFF;
- return ok;
-}
-
-static int write_chr_flash(unsigned int address, unsigned int len, uint8_t* data)
-{
- LED_RED_ON;
- if (address >= 0x8000) address -= 0x8000;
- int ok = 1;
- while (len > 0)
- {
- if (!write_chr_flash_byte(address, *data))
- {
- ok = 0;
- break;
- }
- address++;
- len--;
- data++;
- }
- LED_RED_OFF;
- return ok;
}
void get_mirroring()
@@ -819,7 +687,12 @@ int main (void)
switch (comm_recv_command)
{
case COMMAND_PRG_INIT:
- comm_start(COMMAND_PRG_STARTED, 0);
+ comm_start(COMMAND_PRG_STARTED, 5);
+ comm_send_byte(PROTOCOL_VERSION);
+ comm_send_byte(SEND_BUFFER & 0xFF);
+ comm_send_byte((SEND_BUFFER >> 8) & 0xFF);
+ comm_send_byte(RECV_BUFFER & 0xFF);
+ comm_send_byte((RECV_BUFFER >> 8) & 0xFF);
break;
case COMMAND_PRG_READ_REQUEST:
@@ -847,50 +720,29 @@ int main (void)
read_coolboy_send(address, length);
break;
- case COMMAND_PHI2_INIT:
- phi2_init();
- comm_start(COMMAND_PHI2_INIT_DONE, 0);
- break;
-
case COMMAND_RESET:
reset_phi2();
comm_start(COMMAND_RESET_ACK, 0);
break;
- case COMMAND_PRG_FLASH_ERASE_REQUEST:
- if (erase_prg_flash())
- comm_start(COMMAND_PRG_WRITE_DONE, 0);
- break;
-
- case COMMAND_PRG_FLASH_WRITE_REQUEST:
- address = recv_buffer[0] | ((uint16_t)recv_buffer[1]<<8);
- length = recv_buffer[2] | ((uint16_t)recv_buffer[3]<<8);
- if (write_prg_flash(address, length, (uint8_t*)&recv_buffer[4]))
- comm_start(COMMAND_PRG_WRITE_DONE, 0);
- break;
-
case COMMAND_COOLBOY_ERASE_REQUEST:
- if (erase_coolboy_sector())
- comm_start(COMMAND_PRG_WRITE_DONE, 0);
+ erase_coolboy_sector();
break;
case COMMAND_COOLBOY_WRITE_REQUEST:
address = recv_buffer[0] | ((uint16_t)recv_buffer[1]<<8);
length = recv_buffer[2] | ((uint16_t)recv_buffer[3]<<8);
- if (write_coolboy(address, length, (uint8_t*)&recv_buffer[4]))
- comm_start(COMMAND_PRG_WRITE_DONE, 0);
+ write_coolboy(address, length, (uint8_t*)&recv_buffer[4]);
break;
- case COMMAND_COOLGIRL_ERASE_SECTOR_REQUEST:
- if (erase_coolgirl_sector())
- comm_start(COMMAND_PRG_WRITE_DONE, 0);
+ case COMMAND_FLASH_ERASE_SECTOR_REQUEST:
+ erase_flash_sector();
break;
- case COMMAND_COOLGIRL_WRITE_REQUEST:
+ case COMMAND_FLASH_WRITE_REQUEST:
address = recv_buffer[0] | ((uint16_t)recv_buffer[1]<<8);
length = recv_buffer[2] | ((uint16_t)recv_buffer[3]<<8);
- if (write_coolgirl(address, length, (uint8_t*)&recv_buffer[4]))
- comm_start(COMMAND_PRG_WRITE_DONE, 0);
+ write_flash(address, length, (uint8_t*)&recv_buffer[4]);
break;
case COMMAND_CHR_INIT:
@@ -919,31 +771,6 @@ int main (void)
case COMMAND_MIRRORING_REQUEST:
get_mirroring();
break;
-
- /*
- case COMMAND_EPROM_PREPARE:
- write_eprom_prepare();
- break;
-
- case COMMAND_CHR_EPROM_WRITE_REQUEST:
- address = recv_buffer[0] | ((uint16_t)recv_buffer[1]<<8);
- length = recv_buffer[2] | ((uint16_t)recv_buffer[3]<<8);
- write_eprom(address, length, (uint8_t*)&recv_buffer[4]);
- comm_start(COMMAND_CHR_WRITE_DONE, 0);
- break;
- */
-
- case COMMAND_CHR_FLASH_ERASE_REQUEST:
- if (erase_chr_flash())
- comm_start(COMMAND_CHR_WRITE_DONE, 0);
- break;
-
- case COMMAND_CHR_FLASH_WRITE_REQUEST:
- address = recv_buffer[0] | ((uint16_t)recv_buffer[1]<<8);
- length = recv_buffer[2] | ((uint16_t)recv_buffer[3]<<8);
- if (write_chr_flash(address, length, (uint8_t*)&recv_buffer[4]))
- comm_start(COMMAND_CHR_WRITE_DONE, 0);
- break;
case COMMAND_BOOTLOADER:
cli();
diff --git a/famicom-dumper.hex b/famicom-dumper.hex
index e3e02a1..cc0b890 100644
--- a/famicom-dumper.hex
+++ b/famicom-dumper.hex
@@ -2,301 +2,240 @@
:100010000C9458000C9458000C9458000C94580000
:100020000C9458000C9458000C9458000C945800F0
:100030000C9458000C9458000C9458000C945800E0
-:100040000C9458000C9458000C9484010C945800A3
+:100040000C9458000C9458000C946D010C945800BA
:100050000C9458000C9458000C9458000C945800C0
:100060000C9458000C9458000C9458000C945800B0
:100070000C9458000C9458000C9458000C945800A0
:100080000C9458000C9458000C94580011241FBE76
-:10009000CFEFD0E1DEBFCDBF25E0A0E0B1E001C0F1
-:1000A0001D92A732B207E1F70E942B030C9461095D
+:10009000CFEFD0E1DEBFCDBF29E0A0E0B1E001C0ED
+:1000A0001D92A531B207E1F70E9414030C94780762
:1000B0000C9400008BBB95BB95FD06C0809162003F
:1000C0008061809362000895809162008F7E8093AA
:1000D00062000895CF93DF93C2E6D0E028812E7F9F
:1000E00028832881226028832FEF22BB11BA0E9427
:1000F0005A0088818F7D888382E08A95F1F700C05D
:1001000080B3988190629883988191609883DF9101
-:10011000CF910895CF93DF932FEF22BB11BAC2E6A0
-:10012000D0E02881206828830E945A00888181605D
-:10013000888388818D7F8883C39AC49882E08A955A
-:10014000F1F700C080B3DF91CF9108951F93CF9353
-:10015000DF93C2E6D0E028812E7F288328812260A9
-:1001600028831FEF11BB62BB0E945A0088818B7FDE
-:10017000888382E08A95F1F700C088818460888353
-:1001800012BB11BA1BBA15BA888180618883888135
-:1001900081608883DF91CF911F9108951F93CF9342
-:1001A000DF93162FC49AC39AC2E6D0E0288122605A
-:1001B00028832881206828830E945A009FEF91BBE2
-:1001C00012BB88818160888388818D7F888382E0EB
-:1001D0008A95F1F700C0C39882E08A95F1F700C0D4
-:1001E000C39A1BBA15BA888180618883888182602E
-:1001F000888392BB11BADF91CF911F910895CF935D
-:10020000DF93EC01809162008E7F80936200809189
-:1002100062008260809362008FEF81BB80916200F8
-:100220008F778093620062BBCE010E945A0082E009
-:100230008A95F1F700C0809162008160809362002E
-:1002400080916200D7FD2CC082608093620082E0C2
-:100250008A95F1F700C0809162008E7F80936200E2
-:100260008091620082608093620082E08A95F1F75B
-:1002700000C0809162008068809362008FEF82BB33
-:1002800011BA1BBA15BA8091620080618093620036
-:1002900080916200816080936200DF91CF91089528
-:1002A0008D7F80936200D3CFCF93DF93EC01809159
-:1002B00062008E7F809362008091620082608093F2
-:1002C00062008FEF82BB11BA8091620080688093D8
-:1002D0006200CE010E945A0080916200816080938A
-:1002E000620080916200D7FD0BC082608093620043
-:1002F00082E08A95F1F700C080B3DF91CF91089535
-:100300008D7F80936200F4CF1F920F920FB60F92F1
-:1003100011242F933F934F935F936F937F938F930A
-:100320009F93AF93BF93EF93FF935F9B05C08CB1F7
-:100330000E948F025F99FBCFFF91EF91BF91AF9128
-:100340009F918F917F916F915F914F913F912F91ED
-:100350000F900FBE0F901F901895CF93DF9364E01E
-:1003600070E082E10E945002C69A1BBA15BAC2E63A
-:10037000D0E088818061888382E08A95F1F700C0AF
-:1003800081B182FB882780F90E9478021BBA84E041
-:1003900085BB88818061888382E08A95F1F700C0FF
-:1003A00081B182FB882780F90E9478021BBA88E01D
-:1003B00085BB88818061888382E08A95F1F700C0DF
-:1003C00081B182FB882780F90E9478021BBA8CE0F9
-:1003D00085BB88818061888382E08A95F1F700C0BF
-:1003E00081B182FB882780F90E9478021BBA15BA76
-:1003F000888180618883DF91CF91089581E089B9F8
-:100400001092900088E98AB9E5E9F0E08081866081
-:10041000808308955D9BFECF8CB90895982F9295A7
-:100420009F709A3070F4905D8F708A3040F4805DD8
-:100430005D9BFECF9CB95D9BFECF8CB90895895C16
-:10044000F7CF995CF1CFFC019081992339F0319677
-:100450005D9BFECF9CB991919111FACF0895411502
-:1004600051056105710551F0FC01480F591F81913B
-:100470005D9BFECF8CB9E417F507C9F708959091FD
-:100480000801382F28E05CE8492F4327969540FD66
-:10049000952736952150C1F7909308010C940A02D4
-:1004A0001F93CF93DF93182FEB011092080186E47E
-:1004B0000E943F02812F0E943F028C2F0E943F0228
-:1004C0008D2F0E943F02D0930701C0930601109226
-:1004D000050110920401CD2B21F0DF91CF911F91E6
-:1004E000089580910801DF91CF911F910C940A0229
-:1004F0000E943F0280910401909105010196909322
-:1005000005018093040120910601309107018217B3
-:10051000930709F00895809108010C940A029091C4
-:100520000001992319F0863409F008951092000112
-:1005300060910201709103016115710559F190916B
-:100540000101382F28E05CE8432F4927969540FDAC
-:10055000952736952150C1F79093010161307105BF
-:1005600009F447C0DCF062307105E9F163307105D0
-:1005700039F52091090130910A01A901582B5093B6
-:100580000A01409309016F5F7F4F709303016093ED
-:100590000201089510920B0190E0D3CF611571050F
-:1005A00079F4863481F381E08093000160E070E0AB
-:1005B00082E00E9450026091020170910301E3CF3A
-:1005C0009B01245031092A3154E0350738F5409118
-:1005D000090150910A012417350770F4F901E35F0E
-:1005E000FE4F8083D0CF90E090930A018093090161
-:1005F000CACF80930C01C7CF4091090150910A01E5
-:100600002417350709F0BFCF81E0911113C0809303
-:100610000B01109203011092020108951092030140
-:100620001092020181E08093000160E070E084E0BC
-:100630000C9450028093000160E070E083E00E941F
-:100640005002E7CF109203011092020110920B01A9
-:1006500010920001089578940E94FE0187B3806C87
-:1006600087BB87EB809361008FEF809362001298C5
-:100670001A9A82BB11BA1BBA15BA909162009061A6
-:10068000909362008ABB84BBBC98C498C798C698F4
-:100690000E94220360E070E080E00E945002BEE60B
-:1006A000AB2EB12C8FB589628FBD8EB581608EBDAA
-:1006B00020E030E0E0E041E050E060E070E0809178
-:1006C0000B01811138C08FB589628FBD8EB58160F5
-:1006D0008EBD403187E258076105710508F461C09D
-:1006E000E11164C0C90101968E3691050CF466C013
-:1006F000E1E09C012456310939BD28BD9C01C501AA
-:10070000821B930B853191050CF06AC08B309105EB
-:100710002CF044E150E0481B590BCA01880F991F87
-:10072000909379008093780040E050E0BA01809186
-:100730000B01882341F210920B0110927900109264
-:10074000780019BC18BC1FBC80910C01893109F4D8
-:10075000C2C408F049C08B3009F49EC408F4B6C185
-:10076000813109F4F3C308F0EBC18D3009F42DC5D4
-:100770008F3009F097CF3091620031603093620082
-:10078000209162002E7F2093620080E890E02BBBD6
-:100790003BBB0197E1F760E070E080E10E9450020E
-:1007A00081CF4F5F5F4F6F4F7F4F89CF215031090E
-:1007B00089F4E0E040E050E0BA0181CF8436910551
-:1007C00024F02356310939BD28BD9C0140E050E09A
-:1007D000BA0175CF243631050CF491CFC90189CF08
-:1007E00040E050E0BA016BCF843209F4B2C308F4A0
-:1007F00008C1873209F497C208F096C1853209F41E
-:1008000019C3863209F04ECF80900D0180910E0100
-:10081000912C982A00910F018091100110E0182B63
-:10082000C79A809162008260809362000115110571
-:1008300009F4C9C141E1C42E41E0D42E9401207EC7
-:100840001601F601E401712C06C0CE01807E281746
-:10085000390709F040C081918F3F09F073942196C8
-:10086000015011096F0189F7772009F4ACC160EFDD
-:1008700080E090E80E94FF006AEA8AEA9AE80E9413
-:10088000FF0065E585E595E80E94FF0065E280E0F0
-:1008900090E80E94FF007A94672D80E090E80E9423
-:1008A000FF00F10161911F016F3F89F074016894AD
-:1008B000F7F8C7010E94FF00FFEF8F1A9F0A772009
-:1008C00071F07A94F10161911F016F3F79F72FEF79
-:1008D000821A920AE6CF7110CACF4E01AFCF69E2F9
-:1008E00080E090E80E94FF002AE12A95F1F700C01D
-:1008F00030EA432E36E8532E66246394712C912CF3
-:1009000041E0241A31080CC0FAE1FA95F1F700C071
-:1009100021E0421A510861087108982E09F46AC052
-:10092000C7010E945401909162009260909362000E
-:100930008911EACFF10190819911E6CF01151105D6
-:1009400009F441C14E017ACF00910D0180910E0151
-:1009500010E0182BE0900F0180911001F12CF82A83
-:10096000C79A17FD9DC4E114F10409F4B3C181E1F4
-:10097000882E81E0982EF40171904F0160EF80E0A5
-:1009800090E00E94A6006AEA85E595E00E94A60034
-:1009900065E58AEA92E00E94A60060EA85E595E0B6
-:1009A0000E94A600672DC8010E94A600E801D06839
-:1009B000C12CD12C09C087EC90E00197F1F700C061
-:1009C00000009FEFC91AD90ACE010E946A0078166A
-:1009D00009F463C1EAE0CE16D10469F71BBA15BA6F
-:1009E00080916200806180936200809162008E7FBE
-:1009F0008093620080916200826080936200C79859
-:100A000051CE8B3109F4A0CF08F4F3C0823209F43F
-:100A10006AC2833209F046CEC79AC49AC39ABC9A76
-:100A2000BB9A8091620082608093620060EF80E0F8
-:100A300090E00E94CE006AEA8AEA9AE00E94CE0024
-:100A400065E585E595E00E94CE0060E88AEA9AE0D7
-:100A50000E94CE006AEA8AEA9AE00E94CE0065E52A
-:100A600085E595E00E94CE0060E380E090E00E9482
-:100A7000CE00C0E0D0E00BC0C83BFBE0DF0769F070
-:100A8000EFECF7E03197F1F700C00000219680E02D
-:100A900090E80E948A008F3F79F71BBA15BA8091BF
-:100AA0006200806180936200809162008260809326
-:100AB0006200BC98C498C798C83BDB4009F4F2CDEB
-:100AC00060E070E08AE00E945002ECCD863009F4CC
-:100AD0008AC008F47FC0873009F47CC1893009F0EE
-:100AE000E1CDE0900D0180910E01F12CF82AC0912A
-:100AF0000F0180911001D0E0D82BC79A209769F0A0
-:100B000001E111E0F80161918F01C7010E94FF002E
-:100B1000FFEFEF1AFF0A2197A9F7C79860E070E08E
-:100B20008AE00E945002BECD883209F46DC38E3F28
-:100B300009F0B8CDF89414BEE0E0F8EF0995B2CD15
-:100B4000833109F4CEC0883109F0ACCDC79A60EF8B
-:100B500080E090E80E94FF006AEA8AEA9AE80E9430
-:100B6000FF0065E585E595E80E94FF0060E88AEAF8
-:100B70009AE80E94FF006AEA8AEA9AE80E94FF0067
-:100B800065E585E595E80E94FF0060E18AEA9AE85C
-:100B90000E94FF0006C08FEC97E00197F1F700C0BC
-:100BA000000080E090E80E9454018F3FA1F71BBA3B
-:100BB00015BA80916200806180936200809162002A
-:100BC0008160809362008091620082608093620005
-:100BD000C798A4CF853009F065CD60E070E080E073
-:100BE0000E9450025FCD60E070E081E00E94500200
-:100BF00059CDC79A60EF80E090E00E94A6006AEAB3
-:100C000085E595E00E94A60065E58AEA92E00E94EB
-:100C1000A60060E885E595E00E94A6006AEA85E501
-:100C200095E00E94A60065E58AEA92E00E94A6008F
-:100C300060E185E595E00E94A600C0E0D0E00BC031
-:100C4000C03197E2D90769F08FEC97E00197F1F78F
-:100C500000C00000219680E090E00E946A008F3F73
-:100C600079F71BBA15BA80916200806180936200A7
-:100C70008091620081608093620080916200826056
-:100C800080936200C798C031D74209F40BCD60E071
-:100C900070E08EE00E94500205CD1BBA15BA80911B
-:100CA0006200806180936200809162008E7F8093F9
-:100CB000620080916200826080936200FAE0CF1649
-:100CC000D10409F49CCE0F5F1F4F21E0E21AF10816
-:100CD00009F051CEC79860E070E08EE00E945002AB
-:100CE000E1CCC79AC69A809162008E7F80936200A1
-:100CF000809162008260809362002FEF40E752E0B3
-:100D0000215040405040E1F700C000008091620057
-:100D1000816080936200C798C69860E070E084E1CB
-:100D20000E945002BFCCC0910D0180910E01D0E015
-:100D3000D82B00910F018091100110E0182BC69A5A
-:100D4000CE010E9454010115110509F4B4C280E0DE
-:100D500090E0CBBBD5BBF2E0FA95F1F700C020B331
-:100D6000822728E030E009C09695879541E08427E6
-:100D700040EA94272150310939F080FDF5CF96954E
-:100D8000879521503109C9F70150110921960115A4
-:100D90001105F9F6D82FC92F1BBA15BA8091620038
-:100DA0008061809362008091620081608093620024
-:100DB0008091620082608093620062E070E088E06F
-:100DC0000E9450028D2F0E9478028C2F0E94780280
-:100DD000C69868CC00910D0180910E0110E0182B8F
-:100DE000C0910F0180911001D0E0D82BC69ABE01AE
-:100DF00088E00E945002209751F0C8010E945401DF
-:100E00000E94780221970F5F1F4F2097B1F71BBAFE
-:100E100015BA8091620080618093620080916200C7
-:100E200081608093620080916200826080936200A2
-:100E3000C69838CCC79A60EF80E090E80E94FF0027
-:100E40006AEA8AEA9AE80E94FF0065E585E595E886
-:100E50000E94FF0060E88AEA9AE80E94FF006AEABE
-:100E60008AEA9AE80E94FF0065E585E595E80E9418
-:100E7000FF0060E380E090E80E94FF00C0E0D0E067
-:100E800010C0C83B9BE0D90791F08091620082605E
-:100E9000809362008FEC97E00197F1F700C00000AB
-:100EA000219680E090E80E9454018F3F51F71BBAD1
-:100EB00015BA809162008061809362008091620027
-:100EC0008160809362008091620082608093620002
-:100ED000C798C83BDB4009F4E5CB60E070E08AE0EE
-:100EE0000E945002DFCB00910D0180910E0110E0B5
-:100EF000182BC0910F0180911001D0E0D82BC69A19
-:100F0000C49AC39ABC9ABB9ABE0188E00E94500260
-:100F1000209751F0C8010E948A000E947802219710
-:100F20000F5F1F4F2097B1F71BBA15BA809162006F
-:100F30008061809362008091620082608093620091
-:100F4000C49AC39ABC98C498C698ACCB0E94AD0111
-:100F5000A9CBE0900D0180910E01F12CF82A0091AF
-:100F60000F018091100110E0182BC79AC49AC39A00
-:100F7000BC9ABB9A809162008260809362000115E6
-:100F8000110509F480C061E1C62E61E0D62E9701FB
-:100F9000207E4601F601E701712C05C0CE01807E5E
-:100FA00028173907C1F581918F3F09F07394219675
-:100FB000015011096F0191F7772009F464C06AEAC2
-:100FC0008AEA9AE00E94CE0065E585E595E00E94F8
-:100FD000CE0065E280E090E00E94CE007A94672D1A
-:100FE00080E090E00E94CE00F40161914F016F3FDC
-:100FF00071F0C7010E94CE00C7010196772079F0F9
-:101000007C017A94F40161914F016F3F91F7FFEFFA
-:10101000EF1AFF0AE9CF7110D2CF7E01B8CF69E293
-:1010200080E090E00E94CE00FAE1FA95F1F700C06E
-:101030006894F7F850EA452E56E8552E66246394D6
-:10104000712C312C21E0821A91080CC0FAE1FA953A
-:10105000F1F700C021E0421A510861087108382EEA
-:1010600009F420C1C7010E948A0090916200926039
-:10107000909362008311EACFF40190819311E6CF3F
-:101080000115110551F68091620082608093620023
-:10109000BC98C498C79842CD00910D0180910E0173
-:1010A00010E0182BC0910F0180911001D0E0D82BD7
-:1010B000C69ABE018CE00E945002209709F4A7CE88
-:1010C000C8010E946A000E94780221970F5F1F4F9B
-:1010D0002097B1F79CCEE0900D0180910E01F12C8C
-:1010E000F82A00910F018091100110E0182BC79A87
-:1010F0000115110509F411CD71E1872E71E0972ECC
-:10110000F40161904F0160EF80E090E80E94FF00E1
-:101110006AEA85E595E80E94FF0065E58AEA92E8BB
-:101120000E94FF0060EA85E595E80E94FF00E70164
-:10113000D068662DCE010E94FF00F5E8FA95F1F720
-:101140000000C12CD12C712C0CC025E82A95F1F798
-:1011500000004FEFC41AD40A782E58ECC516D104FB
-:1011600031F1CE010E9454019091620092609093FF
-:1011700062008711EACF6710E8CF80916200826039
-:10118000809362001BBA15BA8091620080618093DF
-:1011900062008AE0C816D1040CF031CC9FEFE91A46
-:1011A000F90A0150110909F0ABCFC798B7CC80916B
-:1011B00062008260809362001BBA15BA809162005F
-:1011C000806180936200C7986DCAE0900D018091A4
-:1011D0000E01F12CF82AC0910F0180911001D0E08E
-:1011E000D82BC79A209709F475CD01E111E0F801D9
-:1011F00061918F01C7010E94A600FFEFEF1AFF0A5D
-:101200002197A9F7C79867CDE0900D0180910E0155
-:10121000F12CF82A00910F018091100110E0182B99
-:10122000C69A0115110509F449C0C0E0D0E0C70114
-:101230000E946A00C82788E090E04C2FD695C79599
-:1012400040FF04C051E0C52750EAD5270197A9F710
-:10125000015011098FEFE81AF80A0115110539F745
-:101260001C2FCD2F1BBA15BA80916200806180932C
-:1012700062008091620081608093620080916200D0
-:1012800082608093620062E070E08CE00E94500215
-:10129000812F0E9478028C2F0E947802C69802CA81
-:1012A000105861CB80916200826080936200BC988C
-:1012B000C498C798F7C9C0E0D0E06ECDC0E010E098
-:0612C000D1CFF894FFCF2E
+:10011000CF910895CF93DF93C2E6D0E028812E7F60
+:1001200028832881226028832FEF22BB11BA2881DF
+:10013000206828830E945A00888181608883888192
+:100140008D7F8883C39AC49882E08A95F1F700C0B6
+:1001500080B3988192609883C49ADF91CF9108957B
+:100160001F93CF93DF93162FBC9ABB9AC49AC39A5E
+:10017000C2E6D0E028812260288328812068288375
+:100180000E945A009FEF91BB12BB888181608883D7
+:1001900088818D7F888382E08A95F1F700C0C398BB
+:1001A00082E08A95F1F700C0C39A1BBA15BA88811C
+:1001B0008061888388818260888392BB11BADF91D5
+:1001C000CF911F910895CF93DF93EC01809162004E
+:1001D0008E7F8093620080916200826080936200D3
+:1001E0008FEF81BB809162008F778093620062BB4A
+:1001F000CE010E945A0082E08A95F1F700C08091FA
+:10020000620081608093620080916200D7FD2CC003
+:1002100082608093620082E08A95F1F700C080914D
+:1002200062008E7F80936200809162008260809382
+:10023000620082E08A95F1F700C0809162008068D8
+:10024000809362008FEF82BB11BA1BBA15BA8091FE
+:10025000620080618093620080916200816080937F
+:100260006200DF91CF9108958D7F80936200D3CF9C
+:10027000CF93DF93EC01809162008E7F80936200C8
+:10028000809162008260809362008FEF82BB11BA1E
+:1002900080916200806880936200CE010E945A00C3
+:1002A0008091620081608093620080916200D7FD3E
+:1002B00010C082608093620082E08A95F1F700C0EE
+:1002C00080B390916200926090936200DF91CF9131
+:1002D00008958D7F80936200EFCF1F920F920FB62B
+:1002E0000F9211242F933F934F935F936F937F93BC
+:1002F0008F939F93AF93BF93EF93FF935F9B05C043
+:100300008CB10E9478025F99FBCFFF91EF91BF9172
+:10031000AF919F918F917F916F915F914F913F919D
+:100320002F910F900FBE0F901F901895CF93DF93D2
+:1003300064E070E082E10E943902C69A1BBA15BAE5
+:10034000C2E6D0E088818061888382E08A95F1F7F7
+:1003500000C081B182FB882780F90E9461021BBA2C
+:1003600084E085BB88818061888382E08A95F1F78B
+:1003700000C081B182FB882780F90E9461021BBA0C
+:1003800088E085BB88818061888382E08A95F1F767
+:1003900000C081B182FB882780F90E9461021BBAEC
+:1003A0008CE085BB88818061888382E08A95F1F743
+:1003B00000C081B182FB882780F90E9461021BBACC
+:1003C00015BA888180618883DF91CF91089581E09B
+:1003D00089B91092900088E98AB9E5E9F0E0808156
+:1003E0008660808308955D9BFECF8CB90895982F19
+:1003F00092959F709A3070F4905D8F708A3040F4BF
+:10040000805D5D9BFECF9CB95D9BFECF8CB908954E
+:10041000895CF7CF995CF1CFFC019081992339F089
+:1004200031965D9BFECF9CB991919111FACF0895C1
+:10043000411551056105710551F0FC01480F591F27
+:1004400081915D9BFECF8CB9E417F507C9F708953C
+:1004500090910801382F28E05CE8492F43279695B2
+:1004600040FD952736952150C1F7909308010C94D3
+:10047000F3011F93CF93DF93182FEB011092080124
+:1004800086E40E942802812F0E9428028C2F0E945D
+:1004900028028D2F0E942802D0930701C0930601E5
+:1004A0001092050110920401CD2B21F0DF91CF9124
+:1004B0001F91089580910801DF91CF911F910C94B5
+:1004C000F3010E9428028091040190910501019698
+:1004D000909305018093040120910601309107015A
+:1004E0008217930709F00895809108010C94F30195
+:1004F00090910001992319F0863409F00895109223
+:10050000000160910201709103016115710559F1BB
+:1005100090910101382F28E05CE8432F49279695F8
+:1005200040FD952736952150C1F790930101613028
+:10053000710509F447C0DCF062307105E9F1633000
+:10054000710539F52091090130910A01A901582B53
+:1005500050930A01409309016F5F7F4F709303012D
+:1005600060930201089510920B0190E0D3CF6115C2
+:10057000710579F4863481F381E08093000160E0B5
+:1005800070E082E00E9439026091020170910301E3
+:10059000E3CF9B0124503109283058E0350738F566
+:1005A0004091090150910A012417350770F4F901AF
+:1005B000E35FFE4F8083D0CF90E090930A01809359
+:1005C0000901CACF80930C01C7CF40910901509116
+:1005D0000A012417350709F0BFCF81E0911113C03C
+:1005E00080930B0110920301109202010895109262
+:1005F00003011092020181E08093000160E070E04D
+:1006000084E00C9439028093000160E070E083E0A4
+:100610000E943902E7CF109203011092020110925A
+:100620000B0110920001089578940E94E70187B3AE
+:10063000806C87BB87EB809361008FEF80936200B3
+:1006400012981A9A82BB11BA1BBA15BA909162001D
+:100650009061909362008ABB84BBBC98C498C79891
+:10066000C6980E940B0360E070E080E00E943902AF
+:10067000CEE68C2E912C8FB589628FBD8EB58160B0
+:100680008EBD20E030E0E0E041E050E060E070E06E
+:1006900080910B01811138C08FB589628FBD8EB5F5
+:1006A00081608EBD403187E258076105710508F40D
+:1006B00050C0E11153C0C90101968E3691050CF46A
+:1006C00055C0E1E09C012456310939BD28BD9C018B
+:1006D000C401821B930B853191050CF059C08B30FE
+:1006E00091052CF044E150E0481B590BCA01880FDA
+:1006F000991F909379008093780040E050E0BA0110
+:1007000080910B01882341F210920B011092790025
+:100710001092780019BC18BC1FBC80910C01833169
+:1007200009F4C8C2C8F1853209F4E6C208F457C01A
+:10073000873209F47DC208F4EEC1883209F45DC342
+:100740008E3F09F098CFF89414BEE0E0F8EF0995D9
+:1007500092CF4F5F5F4F6F4F7F4F9ACF215031093C
+:1007600089F4E0E040E050E0BA0192CF8436910590
+:1007700024F02356310939BD28BD9C0140E050E0EA
+:10078000BA0186CF243631050CF4A2CFC9019ACF25
+:1007900040E050E0BA017CCF893009F4D9C008F0BC
+:1007A00059C0863009F41FC1873009F4F5C085307F
+:1007B00009F061CF65E070E080E00E94390282E0DC
+:1007C0000E94610280E00E94610280E80E94610252
+:1007D00080E00E94610288E00E9461024CCF833277
+:1007E00009F4CAC208F005C1823209F044CF009171
+:1007F0000D0180910E0110E0182BC0910F01809126
+:100800001001D0E0D82BC69AC49AC39ABC9ABB9A5E
+:10081000BE0188E00E943902209751F0C8010E9471
+:100820008A000E94610221970F5F1F4F2097B1F746
+:100830001BBA15BA8091620080618093620080913A
+:100840006200826080936200C49AC39ABC98C49884
+:10085000C69811CF8D3071F1813149F18B3009F09B
+:100860000ACF00910D0180910E0110E0182BC0916C
+:100870000F0180911001D0E0D82BC69ABE018CE008
+:100880000E943902209751F0C8010E946A000E941C
+:10089000610221970F5F1F4F2097B1F71BBA15BA5E
+:1008A00080916200806180936200C698E4CE0E94CD
+:1008B0009601E1CE00910D0180910E0110E0182B00
+:1008C000C0910F0180911001D0E0D82BC79A2097DA
+:1008D000C1F181E1E82E81E0F82EF70191917F01CD
+:1008E000809162008E7F80936200809162008260BE
+:1008F00080936200FFEFF1BB92BBC8010E945A00D7
+:10090000809162008B7F8093620022E02A95F1F74C
+:1009100000C0809162008460809362004FEF42BB10
+:1009200011BA1BBA15BA809162008061809362008F
+:10093000809162008160809362000F5F1F4F21975A
+:1009400061F6C79860E070E08EE00E94390293CEB5
+:1009500000910D0180910E0110E0182BC0910F0144
+:1009600080911001D0E0D82BC79A209771F0F1E167
+:10097000EF2EF1E0FF2EF70161917F01C8010E9487
+:10098000E3000F5F1F4F2197B1F7C79860E070E059
+:100990008AE00E9439026FCE00910D0180910E0114
+:1009A00010E0182BC0910F0180911001D0E0D82BDE
+:1009B000C69ABE0188E00E943902209709F46ECFE2
+:1009C000C8010E9438010E94610221970F5F1F4FEA
+:1009D0002097B1F71BBA15BA8091620080618093AD
+:1009E0006200C69848CE60E070E081E00E94390263
+:1009F00042CEA0900D0180910E01B12CB82A009139
+:100A00000F018091100110E0182BC79A01151105F4
+:100A100009F47AC071E1E72E71E0F72E9501207E8E
+:100A20006701F701E501712C06C0CE01807E281711
+:100A3000390709F03DC081918F3F09F073942196E9
+:100A4000015011097F0189F7772009F45DC060EF3B
+:100A500080E090E00E94B0006AEA8AEA9AE00E9490
+:100A6000B00065E585E595E00E94B00065E280E0B4
+:100A700090E00E94B0007A94672D80E090E00E94A0
+:100A8000B000F60161916F016F3F71F0C5010E94E6
+:100A9000B000C5010196772079F05C017A94F601E7
+:100AA00061916F016F3F91F7FFEFAF1ABF0AE9CF76
+:100AB0007110CDCF5E01B2CF69E280E090E00E947C
+:100AC000B0006894B7F8C5010E948A00382E6FE91B
+:100AD000462E66E8562E66246394712CF1E04F1A78
+:100AE00051086108710809F4DBC1C5010E948A0040
+:100AF000831511F0382EF2CFF6013197808138122C
+:100B0000D6C101151105B1F660E070E08AE00E94DF
+:100B10003902C798B0CDE0900D0180910E01F12C03
+:100B2000F82A00910F018091100110E0182BC79A4C
+:100B30000115110549F341E1C42E41E0D42E97017E
+:100B4000207E5601F601E701712C06C0CE01807EA1
+:100B50002817390709F03FC081918F3F09F073943E
+:100B60002196015011096F0189F7772069F260EF32
+:100B700080E090E80E94E3006AEA8AEA9AE80E942C
+:100B8000E30065E585E595E80E94E30065E280E025
+:100B900090E80E94E3007A94672D80E090E80E943C
+:100BA000E300F50161915F016F3F89F017016894DF
+:100BB00037F8C1010E94E300FFEFEF1AFF0A772028
+:100BC00071F07A94F50161915F016F3F79F72FEF32
+:100BD000E21AF20AE6CF7110CACF7E01B0CF69E205
+:100BE00080E090E80E94E300C1010E943801F82EE5
+:100BF0003FE9432E36E8532E66246394712C21E09E
+:100C0000421A51086108710809F44AC1C1010E94E1
+:100C100038018F1511F0F82EF2CFF5013197808150
+:100C2000F8124FC10115110509F46ECF7E0187CF6F
+:100C3000E0900D0180910E01F12CF82A00910F0136
+:100C40008091100110E0182BC69A0115110509F4C6
+:100C500042C1C0E0D0E0C7010E943801C82788E047
+:100C600090E05C2FD695C79550FF04C0E1E0CE27F9
+:100C7000E0EADE270197A9F701501109FFEFEF1A0B
+:100C8000FF0A0115110539F71C2FCD2F1BBA15BA14
+:100C90008091620080618093620062E070E088E091
+:100CA0000E943902812F0E9461028C2F0E946102F2
+:100CB000C698E1CCC79AC69A809162008E7F8093D5
+:100CC000620080916200826080936200FFEF20E703
+:100CD00042E0F15020404040E1F700C00000809128
+:100CE0006200816080936200C798C69860E070E0FF
+:100CF00084E10E943902BFCCC79A60EF80E090E89F
+:100D00000E94E3006AEA8AEA9AE80E94E30065E545
+:100D100085E595E80E94E30060E88AEA9AE80E9487
+:100D2000E3006AEA8AEA9AE80E94E30065E585E55D
+:100D300095E80E94E30060E380E090E80E94E30011
+:100D400080E090E80E943801C82F5FE3C52E52E48E
+:100D5000D52E5FE0E52EF12C21E0C21AD108E10882
+:100D6000F10809F4BEC080E090E80E9438018C17B9
+:100D700009F489C0C82FF0CFC79A60EF80E090E0F7
+:100D80000E94B0006AEA8AEA9AE00E94B00065E533
+:100D900085E595E00E94B00060E88AEA9AE00E944A
+:100DA000B0006AEA8AEA9AE00E94B00065E585E54B
+:100DB00095E00E94B00060E380E090E00E94B00007
+:100DC00080E090E80E948A00C82FEFE3CE2EE2E494
+:100DD000DE2EEFE0EE2EF12C51E0C51AD108E1082D
+:100DE000F10809F47EC080E090E80E948A00D82FC4
+:100DF0008C278474D9F1CD2FEFCFE0900D01809135
+:100E00000E01F12CF82A00910F018091100110E0E1
+:100E1000182BC69A0115110509F460C0C0E0D0E096
+:100E2000C7010E946A00C82788E090E04C2FD69541
+:100E3000C79540FF04C051E0C52750EAD527019768
+:100E4000A9F7015011098FEFE81AF80A01151105E9
+:100E500039F71C2FCD2F1BBA15BA80916200806123
+:100E60008093620062E070E08CE01ACFDF3F09F40B
+:100E70004BCE61E070E08BE20E9439028D2F0E9420
+:100E80006102C798F8CBCF3F09F43ECE61E070E035
+:100E90008BE20E9439028C2F0E946102C798EBCB33
+:100EA00060E070E08AE20E943902C798E4CB61E01A
+:100EB00070E089E20E943902832D0E946102C79886
+:100EC000DACB61E070E089E20E9439028F2D0E9446
+:100ED0006102C798D0CBC0E010E0D8CEC0E010E0EF
+:100EE000BACF60E070E08CE20E943902C798C3CBB1
+:040EF000F894FFCFA4
:00000001FF