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-07-24 13:34:40 +0300
committerCluster <clusterrr@clusterrr.com>2020-07-24 13:34:40 +0300
commitc8eeed0826939a9c793d311244e5721f77aa6e73 (patch)
tree5d207f0fcf2b0b5a3468868952cb753e2b5c6bbb
parent8a2d12407b61d9ccee7b3d606951a16886544cc9 (diff)
Fixes
-rw-r--r--dumper.c1525
-rw-r--r--famicom-dumper.hex820
2 files changed, 1292 insertions, 1053 deletions
diff --git a/dumper.c b/dumper.c
index c2f75b0..40dd0a2 100644
--- a/dumper.c
+++ b/dumper.c
@@ -52,901 +52,904 @@ static void (*jump_to_bootloader)(void) = (void*)0xF800;
ISR(USART0_RX_vect)
{
- unsigned char b;
- while (UCSR0A & (1<<RXC0))
- {
- b = UDR0;
- comm_proceed(b);
- }
+ unsigned char b;
+ while (UCSR0A & (1<<RXC0))
+ {
+ b = UDR0;
+ comm_proceed(b);
+ }
}
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--;
- }
+ 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;
- unsigned char h = address>>8;
-
- PORTA = l;
- PORTC = h;
-
- // PPU /A13
- if ((address >> 13) & 1)
- PORTF &= ~(1<<4);
- else
- PORTF |= 1<<4;
+ unsigned char l = address & 0xFF;
+ unsigned char h = address>>8;
+
+ PORTA = l;
+ PORTC = h;
+
+ // PPU /A13
+ if ((address >> 13) & 1)
+ PORTF &= ~(1<<4);
+ else
+ PORTF |= 1<<4;
}
static void set_romsel(unsigned int address)
{
- if (address & 0x8000)
- {
- ROMSEL_LOW;
- } else {
- ROMSEL_HI;
- }
+ if (address & 0x8000)
+ {
+ ROMSEL_LOW;
+ } else {
+ ROMSEL_HI;
+ }
}
static unsigned char read_prg_byte(unsigned int address)
{
- PHI2_LOW;
+ PHI2_LOW;
ROMSEL_HI;
- MODE_READ;
- PRG_READ;
- set_address(address);
+ MODE_READ;
+ PRG_READ;
+ set_address(address);
+ //_delay_us(1);
+
+ PHI2_HI;
+ set_romsel(address); // set /ROMSEL high if need
_delay_us(1);
- PHI2_HI;
- set_romsel(address);
- _delay_us(1);
- return PIND;
+ uint8_t result = PIND;
+ return result;
}
static unsigned char read_chr_byte(unsigned int address)
{
- MODE_READ;
- PHI2_HI;
- ROMSEL_HI;
- set_address(address);
- CHR_READ_LOW;
-
- _delay_us(1);
-
- uint8_t result = PIND;
-
- CHR_READ_HI;
- return result;
+ PHI2_LOW;
+ 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;
+ return result;
}
static unsigned char read_coolboy_byte(unsigned int address)
{
- MODE_READ;
- PRG_READ;
- set_address(address);
- PHI2_HI;
- ROMSEL_LOW;
- COOLBOY_PORT |= 1<<COOLBOY_WR_PIN;
- COOLBOY_PORT &= ~(1<<COOLBOY_RD_PIN);
- _delay_us(1);
- return PIND;
+ MODE_READ;
+ PRG_READ;
+ set_address(address);
+ PHI2_HI;
+ ROMSEL_LOW;
+ COOLBOY_PORT |= 1<<COOLBOY_WR_PIN;
+ COOLBOY_PORT &= ~(1<<COOLBOY_RD_PIN);
+ _delay_us(1);
+ return PIND;
}
static void read_prg_send(unsigned int address, unsigned int len)
{
- LED_GREEN_ON;
- comm_start(COMMAND_PRG_READ_RESULT, len);
- while (len > 0)
- {
- comm_send_byte(read_prg_byte(address));
- len--;
- address++;
- }
- set_address(0);
- PHI2_HI;
- ROMSEL_HI;
- LED_GREEN_OFF;
+ LED_GREEN_ON;
+ comm_start(COMMAND_PRG_READ_RESULT, len);
+ while (len > 0)
+ {
+ comm_send_byte(read_prg_byte(address));
+ len--;
+ address++;
+ }
+ set_address(0);
+ PHI2_HI;
+ ROMSEL_HI;
+ LED_GREEN_OFF;
}
static void read_chr_send(unsigned int address, unsigned int len)
{
- LED_GREEN_ON;
- comm_start(COMMAND_CHR_READ_RESULT, len);
- while (len > 0)
- {
- comm_send_byte(read_chr_byte(address));
- len--;
- address++;
- }
- set_address(0);
- PHI2_HI;
- ROMSEL_HI;
- LED_GREEN_OFF;
+ LED_GREEN_ON;
+ comm_start(COMMAND_CHR_READ_RESULT, len);
+ while (len > 0)
+ {
+ comm_send_byte(read_chr_byte(address));
+ len--;
+ address++;
+ }
+ set_address(0);
+ PHI2_HI;
+ ROMSEL_HI;
+ LED_GREEN_OFF;
}
static uint16_t crc16_update(uint16_t crc, uint8_t a)
{
- int i;
- crc ^= a;
- for (i = 0; i < 8; ++i)
- {
- if (crc & 1)
- crc = (crc >> 1) ^ 0xA001;
- else
- crc = (crc >> 1);
- }
- return crc;
+ int i;
+ crc ^= a;
+ for (i = 0; i < 8; ++i)
+ {
+ if (crc & 1)
+ crc = (crc >> 1) ^ 0xA001;
+ else
+ crc = (crc >> 1);
+ }
+ return crc;
}
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);
- 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);
- LED_GREEN_OFF;
+ 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);
+ 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);
+ LED_GREEN_OFF;
}
static void read_chr_crc_send(unsigned int address, unsigned int len)
{
- LED_GREEN_ON;
- uint16_t crc = 0;
- while (len > 0)
- {
- crc = crc16_update(crc, read_chr_byte(address));
- 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);
- LED_GREEN_OFF;
+ LED_GREEN_ON;
+ uint16_t crc = 0;
+ while (len > 0)
+ {
+ crc = crc16_update(crc, read_chr_byte(address));
+ 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);
+ LED_GREEN_OFF;
}
static void read_coolboy_send(unsigned int address, unsigned int len)
{
- LED_GREEN_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;
- comm_start(COMMAND_PRG_READ_RESULT, len);
- while (len > 0)
- {
- comm_send_byte(read_coolboy_byte(address));
- len--;
- address++;
- }
- set_address(0);
- ROMSEL_HI;
- COOLBOY_PORT |= 1<<COOLBOY_RD_PIN;
- COOLBOY_PORT |= 1<<COOLBOY_WR_PIN;
-
- COOLBOY_DDR &= ~((1<<COOLBOY_RD_PIN) | (1<<COOLBOY_RD_PIN));
- COOLBOY_PORT &= ~((1<<COOLBOY_RD_PIN) | (1<<COOLBOY_RD_PIN));
+ LED_GREEN_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;
+ comm_start(COMMAND_PRG_READ_RESULT, len);
+ while (len > 0)
+ {
+ comm_send_byte(read_coolboy_byte(address));
+ len--;
+ address++;
+ }
+ set_address(0);
+ ROMSEL_HI;
+ COOLBOY_PORT |= 1<<COOLBOY_RD_PIN;
+ COOLBOY_PORT |= 1<<COOLBOY_WR_PIN;
+
+ COOLBOY_DDR &= ~((1<<COOLBOY_RD_PIN) | (1<<COOLBOY_RD_PIN));
+ COOLBOY_PORT &= ~((1<<COOLBOY_RD_PIN) | (1<<COOLBOY_RD_PIN));
LED_GREEN_OFF;
}
static void write_prg_byte(unsigned int address, uint8_t data)
{
- PHI2_LOW;
- ROMSEL_HI;
- MODE_WRITE;
- PRG_WRITE;
- PORTD = data;
- set_address(address); // PHI2 low, ROMSEL always HIGH
- _delay_us(1);
-
- PHI2_HI;
- set_romsel(address); // ROMSEL is low if need, PHI2 high
-
- _delay_us(1); // WRITING
-
- // PHI2 low, ROMSEL high
- PHI2_LOW;
- ROMSEL_HI;
-
- // Back to read mode
- _delay_us(1);
- PRG_READ;
- MODE_READ;
- set_address(0);
-
- // Set phi2 to high state to keep cartridge unreseted
- PHI2_HI;
+ PHI2_LOW;
+ ROMSEL_HI;
+ MODE_WRITE;
+ PRG_WRITE;
+ PORTD = data;
+ set_address(address); // PHI2 low, ROMSEL always HIGH
+ _delay_us(1);
+
+ PHI2_HI;
+ set_romsel(address); // ROMSEL is low if need, PHI2 high
+
+ _delay_us(1); // WRITING
+
+ // PHI2 low, ROMSEL high
+ PHI2_LOW;
+ ROMSEL_HI;
+
+ // Back to read mode
+ _delay_us(1);
+ PRG_READ;
+ MODE_READ;
+ set_address(0);
+
+ // Set phi2 to high state to keep cartridge unreseted
+ PHI2_HI;
}
static void write_chr_byte(unsigned int address, uint8_t data)
{
- PHI2_LOW;
- ROMSEL_HI;
- MODE_WRITE;
- PORTD = data;
- set_address(address); // PHI2 low, ROMSEL always HIGH
- CHR_WRITE_LOW;
-
- _delay_us(1); // WRITING
-
- CHR_WRITE_HI;
-
- MODE_READ;
- set_address(0);
- PHI2_HI;
+ PHI2_LOW;
+ ROMSEL_HI;
+ MODE_WRITE;
+ PORTD = data;
+ set_address(address); // PHI2 low, ROMSEL always HIGH
+ CHR_WRITE_LOW;
+
+ _delay_us(1); // WRITING
+
+ CHR_WRITE_HI;
+
+ MODE_READ;
+ set_address(0);
+ PHI2_HI;
}
static void write_prg(unsigned int address, unsigned int len, uint8_t* data)
{
- LED_RED_ON;
- while (len > 0)
- {
- write_prg_byte(address, *data);
- address++;
- len--;
- data++;
- }
- LED_RED_OFF;
+ LED_RED_ON;
+ while (len > 0)
+ {
+ write_prg_byte(address, *data);
+ address++;
+ len--;
+ data++;
+ }
+ LED_RED_OFF;
}
static void write_chr(unsigned int address, unsigned int len, uint8_t* data)
{
- LED_RED_ON;
- while (len > 0)
- {
- write_chr_byte(address, *data);
- address++;
- len--;
- data++;
- }
- LED_RED_OFF;
+ LED_RED_ON;
+ while (len > 0)
+ {
+ write_chr_byte(address, *data);
+ address++;
+ len--;
+ data++;
+ }
+ LED_RED_OFF;
}
static void write_prg_flash_command(unsigned int address, uint8_t data)
{
- write_prg_byte(address | 0x8000, data);
+ write_prg_byte(address | 0x8000, data);
}
static void write_coolboy_flash_command(unsigned int address, uint8_t data)
{
- COOLBOY_PORT |= 1<<COOLBOY_RD_PIN;
- COOLBOY_PORT |= 1<<COOLBOY_WR_PIN;
- ROMSEL_HI;
- PRG_READ;
- set_address(address);
- MODE_WRITE;
- PORTD = data;
- PHI2_HI;
- ROMSEL_LOW;
- _delay_us(1);
-
- PORTB &= ~(1<<COOLBOY_WR_PIN);
-
- _delay_us(1);
-
- PORTB |= 1<<COOLBOY_WR_PIN;
- set_address(0);
- ROMSEL_HI;
- MODE_READ;
+ COOLBOY_PORT |= 1<<COOLBOY_RD_PIN;
+ COOLBOY_PORT |= 1<<COOLBOY_WR_PIN;
+ ROMSEL_HI;
+ PRG_READ;
+ set_address(address);
+ MODE_WRITE;
+ PORTD = data;
+ PHI2_HI;
+ ROMSEL_LOW;
+ _delay_us(1);
+
+ PORTB &= ~(1<<COOLBOY_WR_PIN);
+
+ _delay_us(1);
+
+ PORTB |= 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);
+ 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;
+ 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;
+ 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;
+ 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()
{
- 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);
-
- int timeout = 0;
- uint8_t debug;
- while (((debug = read_coolboy_byte(0x8000)) != 0xFF) && (timeout < 3000))
- {
- //comm_start(0xFF, 1);
- //comm_send_byte(debug);
- _delay_ms(1);
- timeout++;
- }
-
- 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;
+ 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);
+
+ int timeout = 0;
+ uint8_t debug;
+ while (((debug = read_coolboy_byte(0x8000)) != 0xFF) && (timeout < 3000))
+ {
+ //comm_start(0xFF, 1);
+ //comm_send_byte(debug);
+ _delay_ms(1);
+ timeout++;
+ }
+
+ 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()
{
- 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(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;
+ 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(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))
- {
- _delay_ms(1);
- timeout++;
- }
- set_address(0);
- PHI2_HI;
- ROMSEL_HI;
-
- LED_RED_OFF;
- return timeout < 10000;
+ 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))
+ {
+ _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))
- {
- ok = 0;
- break;
- }
- address++;
- len--;
- data++;
- }
- LED_RED_OFF;
- return ok;
+ LED_RED_ON;
+ int ok = 1;
+ while (len > 0)
+ {
+ if (!write_prg_flash_byte(address, *data))
+ {
+ ok = 0;
+ break;
+ }
+ address++;
+ len--;
+ data++;
+ }
+ LED_RED_OFF;
+ return ok;
}
static int 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))
- {
- if (*d != 0xFF) count++;
- a++;
- len--;
- d++;
- }
-
- if (count)
- {
- //write_prg_flash_command(0x0000, 0xF0);
- write_coolboy_flash_command(0x0AAA, 0xAA);
- write_coolboy_flash_command(0x0555, 0x55);
- write_coolboy_flash_command(0x0000, 0x25);
- write_coolboy_flash_command(0x0000, count-1);
-
- while (count > 0)
- {
- if (*data != 0xFF)
- {
- write_coolboy_flash_command(address, *data);
- count--;
- }
- address++;
- data++;
- }
-
- write_coolboy_flash_command(0x0000, 0x29);
- _delay_us(10);
-
- long int timeout = 0;
- uint8_t res, last_res = 0;
- while (timeout < 100000)
- {
- 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;
- }
- }
-
- 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));
- LED_RED_OFF;
- return ok;
+ 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))
+ {
+ if (*d != 0xFF) count++;
+ a++;
+ len--;
+ d++;
+ }
+
+ if (count)
+ {
+ //write_prg_flash_command(0x0000, 0xF0);
+ write_coolboy_flash_command(0x0AAA, 0xAA);
+ write_coolboy_flash_command(0x0555, 0x55);
+ write_coolboy_flash_command(0x0000, 0x25);
+ write_coolboy_flash_command(0x0000, count-1);
+
+ while (count > 0)
+ {
+ if (*data != 0xFF)
+ {
+ write_coolboy_flash_command(address, *data);
+ count--;
+ }
+ address++;
+ data++;
+ }
+
+ write_coolboy_flash_command(0x0000, 0x29);
+ _delay_us(10);
+
+ long int timeout = 0;
+ uint8_t res, last_res = 0;
+ while (timeout < 100000)
+ {
+ 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;
+ }
+ }
+
+ 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));
+ LED_RED_OFF;
+ return ok;
}
static int write_coolgirl(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))
- {
- if (*d != 0xFF)
- count++;
- a++;
- len--;
- d++;
- }
-
- if (count)
- {
- write_prg_flash_command(0x0000, 0xF0);
- write_prg_flash_command(0x0AAA, 0xAA);
- write_prg_flash_command(0x0555, 0x55);
- write_prg_flash_command(0x0000, 0x25);
- write_prg_flash_command(0x0000, count-1);
-
- while (count > 0)
- {
- if (*data != 0xFF)
- {
- write_prg_flash_command(address, *data);
- count--;
- }
- address++;
- data++;
- }
-
- write_prg_flash_command(0x0000, 0x29);
- _delay_us(10);
-
- long int timeout = 0;
- uint8_t res, last_res = 0;
- while (timeout < 100000)
- {
- 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;
- }
- }
-
- address = a;
- data = d;
- }
- ROMSEL_HI;
- LED_RED_OFF;
- return ok;
+ 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))
+ {
+ if (*d != 0xFF)
+ count++;
+ a++;
+ len--;
+ d++;
+ }
+
+ if (count)
+ {
+ write_prg_flash_command(0x0000, 0xF0);
+ write_prg_flash_command(0x0AAA, 0xAA);
+ write_prg_flash_command(0x0555, 0x55);
+ write_prg_flash_command(0x0000, 0x25);
+ write_prg_flash_command(0x0000, count-1);
+
+ while (count > 0)
+ {
+ if (*data != 0xFF)
+ {
+ write_prg_flash_command(address, *data);
+ count--;
+ }
+ address++;
+ data++;
+ }
+
+ write_prg_flash_command(0x0000, 0x29);
+ _delay_us(10);
+
+ long int timeout = 0;
+ uint8_t res, last_res = 0;
+ while (timeout < 100000)
+ {
+ 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;
+ }
+ }
+
+ address = a;
+ data = d;
+ }
+ ROMSEL_HI;
+ 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;
+ 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()
{
- comm_start(COMMAND_MIRRORING_RESULT, 4);
- LED_GREEN_ON;
- set_address(0);
- _delay_us(1);
- comm_send_byte((PINE >> 2) & 1);
- set_address(1<<10);
- _delay_us(1);
- comm_send_byte((PINE >> 2) & 1);
- set_address(1<<11);
- _delay_us(1);
- comm_send_byte((PINE >> 2) & 1);
- set_address((1<<10) | (1<<11));
- _delay_us(1);
- comm_send_byte((PINE >> 2) & 1);
- set_address(0);
+ comm_start(COMMAND_MIRRORING_RESULT, 4);
+ LED_GREEN_ON;
+ set_address(0);
+ _delay_us(1);
+ comm_send_byte((PINE >> 2) & 1);
+ set_address(1<<10);
+ _delay_us(1);
+ comm_send_byte((PINE >> 2) & 1);
+ set_address(1<<11);
+ _delay_us(1);
+ comm_send_byte((PINE >> 2) & 1);
+ set_address((1<<10) | (1<<11));
+ _delay_us(1);
+ comm_send_byte((PINE >> 2) & 1);
+ set_address(0);
}
static void init_ports()
{
- DDRB |= (1 << 6) | (1 << 7); // LEDS
- DDRF = 0b10110111; // CPU R/W, IRQ, PPU /RD, PPU /A13, CIRAM /CE, PPU /WR, /ROMSEL, PHI2
- PORTF = 0b11111111; // CPU R/W, IRQ, PPU /RD, PPU /A13, CIRAM /CE, PPU /WR, /ROMSEL, PHI2
- DDRE &= ~(1<<2); // CIRAM A10
- PORTE |= 1<<2; // CIRAM A10
- MODE_READ;
- set_address(0);
- DDRA = 0xFF; // Address low
- DDRC = 0xFF; // Address high
+ DDRB |= (1 << 6) | (1 << 7); // LEDS
+ DDRF = 0b10110111; // CPU R/W, IRQ, PPU /RD, PPU /A13, CIRAM /CE, PPU /WR, /ROMSEL, PHI2
+ PORTF = 0b11111111; // CPU R/W, IRQ, PPU /RD, PPU /A13, CIRAM /CE, PPU /WR, /ROMSEL, PHI2
+ DDRE &= ~(1<<2); // CIRAM A10
+ PORTE |= 1<<2; // CIRAM A10
+ MODE_READ;
+ set_address(0);
+ DDRA = 0xFF; // Address low
+ DDRC = 0xFF; // Address high
}
static void reset_phi2()
{
- LED_RED_ON;
- LED_GREEN_ON;
- PHI2_LOW;
- ROMSEL_HI;
- _delay_ms(100);
- PHI2_HI;
- LED_RED_OFF;
- LED_GREEN_OFF;
+ LED_RED_ON;
+ LED_GREEN_ON;
+ PHI2_LOW;
+ ROMSEL_HI;
+ _delay_ms(100);
+ PHI2_HI;
+ LED_RED_OFF;
+ LED_GREEN_OFF;
}
int main (void)
{
- sei();
- USART_init();
- init_ports();
- COOLBOY_DDR &= ~((1<<COOLBOY_RD_PIN) | (1<<COOLBOY_RD_PIN));
- COOLBOY_PORT &= ~((1<<COOLBOY_RD_PIN) | (1<<COOLBOY_RD_PIN));
-
- LED_RED_OFF;
- LED_GREEN_OFF;
-
- comm_init();
- comm_start(COMMAND_PRG_STARTED, 0);
-
- uint16_t address;
- uint16_t length;
-
- unsigned long int t = 0;
- char led_down = 0;
- int led_bright = 0;
-
- while (1)
- {
- TCCR1A |= (1<<COM1C1) | (1<<COM1B1) | (1<<WGM10);
- TCCR1B |= (1<<CS10);
- if (t++ >= 10000)
- {
- if (!led_down)
- {
- led_bright++;
- if (led_bright >= 110) led_down = 1;
- } else {
- led_bright--;
- if (!led_bright) led_down = 0;
- }
- if (led_bright >= 100) OCR1B = led_bright - 100;
- if (led_down)
- {
- int led_bright2 = 110-led_bright;
- if (led_bright2 <= 20)
- {
- if (led_bright2 > 10) led_bright2 = 20 - led_bright2;
- OCR1C = led_bright2*2;
- }
- }
- t = 0;
- }
-
- if (comm_recv_done)
- {
- comm_recv_done = 0;
- t = led_down = led_bright = 0;
- TCCR1A = OCR1B = OCR1C = 0;
-
- switch (comm_recv_command)
- {
- case COMMAND_PRG_INIT:
- comm_start(COMMAND_PRG_STARTED, 0);
- break;
-
- case COMMAND_PRG_READ_REQUEST:
- address = recv_buffer[0] | ((uint16_t)recv_buffer[1]<<8);
- length = recv_buffer[2] | ((uint16_t)recv_buffer[3]<<8);
- read_prg_send(address, length);
- break;
-
- case COMMAND_PRG_CRC_READ_REQUEST:
- address = recv_buffer[0] | ((uint16_t)recv_buffer[1]<<8);
- length = recv_buffer[2] | ((uint16_t)recv_buffer[3]<<8);
- read_prg_crc_send(address, length);
- break;
-
- case COMMAND_PRG_WRITE_REQUEST:
- address = recv_buffer[0] | ((uint16_t)recv_buffer[1]<<8);
- length = recv_buffer[2] | ((uint16_t)recv_buffer[3]<<8);
- write_prg(address, length, (uint8_t*)&recv_buffer[4]);
- comm_start(COMMAND_PRG_WRITE_DONE, 0);
- break;
-
- case COMMAND_COOLBOY_READ_REQUEST:
- address = recv_buffer[0] | ((uint16_t)recv_buffer[1]<<8);
- length = recv_buffer[2] | ((uint16_t)recv_buffer[3]<<8);
- 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);
- 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);
- break;
-
- case COMMAND_COOLGIRL_ERASE_SECTOR_REQUEST:
- if (erase_coolgirl_sector())
- comm_start(COMMAND_PRG_WRITE_DONE, 0);
- break;
-
- case COMMAND_COOLGIRL_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);
- break;
-
- case COMMAND_CHR_INIT:
- comm_start(COMMAND_CHR_STARTED, 0);
- break;
-
- case COMMAND_CHR_READ_REQUEST:
- address = recv_buffer[0] | ((uint16_t)recv_buffer[1]<<8);
- length = recv_buffer[2] | ((uint16_t)recv_buffer[3]<<8);
- read_chr_send(address, length);
- break;
-
- case COMMAND_CHR_CRC_READ_REQUEST:
- address = recv_buffer[0] | ((uint16_t)recv_buffer[1]<<8);
- length = recv_buffer[2] | ((uint16_t)recv_buffer[3]<<8);
- read_chr_crc_send(address, length);
- break;
-
- case COMMAND_CHR_WRITE_REQUEST:
- address = recv_buffer[0] | ((uint16_t)recv_buffer[1]<<8);
- length = recv_buffer[2] | ((uint16_t)recv_buffer[3]<<8);
- write_chr(address, length, (uint8_t*)&recv_buffer[4]);
- comm_start(COMMAND_CHR_WRITE_DONE, 0);
- break;
-
- 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();
- MCUCSR = 0;
- jump_to_bootloader();
- }
- }
- }
+ sei();
+ USART_init();
+ init_ports();
+ COOLBOY_DDR &= ~((1<<COOLBOY_RD_PIN) | (1<<COOLBOY_RD_PIN));
+ COOLBOY_PORT &= ~((1<<COOLBOY_RD_PIN) | (1<<COOLBOY_RD_PIN));
+
+ LED_RED_OFF;
+ LED_GREEN_OFF;
+
+ comm_init();
+ comm_start(COMMAND_PRG_STARTED, 0);
+
+ uint16_t address;
+ uint16_t length;
+
+ unsigned long int t = 0;
+ char led_down = 0;
+ int led_bright = 0;
+
+ while (1)
+ {
+ TCCR1A |= (1<<COM1C1) | (1<<COM1B1) | (1<<WGM10);
+ TCCR1B |= (1<<CS10);
+ if (t++ >= 10000)
+ {
+ if (!led_down)
+ {
+ led_bright++;
+ if (led_bright >= 110) led_down = 1;
+ } else {
+ led_bright--;
+ if (!led_bright) led_down = 0;
+ }
+ if (led_bright >= 100) OCR1B = led_bright - 100;
+ if (led_down)
+ {
+ int led_bright2 = 110-led_bright;
+ if (led_bright2 <= 20)
+ {
+ if (led_bright2 > 10) led_bright2 = 20 - led_bright2;
+ OCR1C = led_bright2*2;
+ }
+ }
+ t = 0;
+ }
+
+ if (comm_recv_done)
+ {
+ comm_recv_done = 0;
+ t = led_down = led_bright = 0;
+ TCCR1A = OCR1B = OCR1C = 0;
+
+ switch (comm_recv_command)
+ {
+ case COMMAND_PRG_INIT:
+ comm_start(COMMAND_PRG_STARTED, 0);
+ break;
+
+ case COMMAND_PRG_READ_REQUEST:
+ address = recv_buffer[0] | ((uint16_t)recv_buffer[1]<<8);
+ length = recv_buffer[2] | ((uint16_t)recv_buffer[3]<<8);
+ read_prg_send(address, length);
+ break;
+
+ case COMMAND_PRG_CRC_READ_REQUEST:
+ address = recv_buffer[0] | ((uint16_t)recv_buffer[1]<<8);
+ length = recv_buffer[2] | ((uint16_t)recv_buffer[3]<<8);
+ read_prg_crc_send(address, length);
+ break;
+
+ case COMMAND_PRG_WRITE_REQUEST:
+ address = recv_buffer[0] | ((uint16_t)recv_buffer[1]<<8);
+ length = recv_buffer[2] | ((uint16_t)recv_buffer[3]<<8);
+ write_prg(address, length, (uint8_t*)&recv_buffer[4]);
+ comm_start(COMMAND_PRG_WRITE_DONE, 0);
+ break;
+
+ case COMMAND_COOLBOY_READ_REQUEST:
+ address = recv_buffer[0] | ((uint16_t)recv_buffer[1]<<8);
+ length = recv_buffer[2] | ((uint16_t)recv_buffer[3]<<8);
+ 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);
+ 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);
+ break;
+
+ case COMMAND_COOLGIRL_ERASE_SECTOR_REQUEST:
+ if (erase_coolgirl_sector())
+ comm_start(COMMAND_PRG_WRITE_DONE, 0);
+ break;
+
+ case COMMAND_COOLGIRL_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);
+ break;
+
+ case COMMAND_CHR_INIT:
+ comm_start(COMMAND_CHR_STARTED, 0);
+ break;
+
+ case COMMAND_CHR_READ_REQUEST:
+ address = recv_buffer[0] | ((uint16_t)recv_buffer[1]<<8);
+ length = recv_buffer[2] | ((uint16_t)recv_buffer[3]<<8);
+ read_chr_send(address, length);
+ break;
+
+ case COMMAND_CHR_CRC_READ_REQUEST:
+ address = recv_buffer[0] | ((uint16_t)recv_buffer[1]<<8);
+ length = recv_buffer[2] | ((uint16_t)recv_buffer[3]<<8);
+ read_chr_crc_send(address, length);
+ break;
+
+ case COMMAND_CHR_WRITE_REQUEST:
+ address = recv_buffer[0] | ((uint16_t)recv_buffer[1]<<8);
+ length = recv_buffer[2] | ((uint16_t)recv_buffer[3]<<8);
+ write_chr(address, length, (uint8_t*)&recv_buffer[4]);
+ comm_start(COMMAND_CHR_WRITE_DONE, 0);
+ break;
+
+ 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();
+ MCUCSR = 0;
+ jump_to_bootloader();
+ }
+ }
+ }
}
diff --git a/famicom-dumper.hex b/famicom-dumper.hex
index 216fac6..edfb6da 100644
--- a/famicom-dumper.hex
+++ b/famicom-dumper.hex
@@ -2,301 +2,537 @@
:100010000C9458000C9458000C9458000C94580000
:100020000C9458000C9458000C9458000C945800F0
:100030000C9458000C9458000C9458000C945800E0
-:100040000C9458000C9458000C9485010C945800A2
+:100040000C9458000C9458000C94F1010C94580036
:100050000C9458000C9458000C9458000C945800C0
:100060000C9458000C9458000C9458000C945800B0
:100070000C9458000C9458000C9458000C945800A0
:100080000C9458000C9458000C94580011241FBE76
:10009000CFEFD0E1DEBFCDBF25E0A0E0B1E001C0F1
-:1000A0001D92A732B207E1F70E942C030C9462095B
-:1000B0000C9400008BBB95BB95FD06C0809162003F
-:1000C0008061809362000895809162008F7E8093AA
-:1000D00062000895CF93DF932FEF22BB11BAC2E6DF
-:1000E000D0E02881216028832881226028830E9413
-:1000F0005A0088818F7D888382E08A95F1F700C05D
-:1001000080B3988190629883DF91CF910895CF93C7
-:10011000DF932FEF22BB11BAC2E6D0E0288120681E
-:1001200028830E945A0088818160888388818D7F1E
-:100130008883C39AC49882E08A95F1F700C080B39F
-:10014000DF91CF9108951F93CF93DF93C2E6D0E064
-:1001500028812E7F28832881226028831FEF11BBEE
-:1001600062BB0E945A0088818B7F888382E08A95D7
-:10017000F1F700C088818460888312BB11BA1BBA72
-:1001800015BA888180618883888181608883DF9146
-:10019000CF911F9108951F93CF93DF93162FC49A89
-:1001A000C39AC2E6D0E02881226028832881206893
-:1001B00028830E945A009FEF91BB12BB8881816007
-:1001C000888388818D7F888382E08A95F1F700C0DB
-:1001D000C39882E08A95F1F700C0C39A1BBA15BA9A
-:1001E00088818061888388818260888392BB11BA0C
-:1001F000DF91CF911F910895CF93DF93EC01809110
-:1002000062008E7F809362008091620082608093A2
-:1002100062008FEF81BB809162008F7780936200D4
-:1002200062BBCE010E945A0082E08A95F1F700C0BD
-:100230008091620081608093620080916200D7FDAE
-:100240002CC082608093620082E08A95F1F700C042
-:10025000809162008E7F8093620080916200826054
-:100260008093620082E08A95F1F700C0809162007D
-:100270008068809362008FEF82BB11BA1BBA15BAF7
-:100280008091620080618093620080916200816051
-:1002900080936200DF91CF9108958D7F80936200FB
-:1002A000D3CFCF93DF93EC01809162008E7F809358
-:1002B0006200809162008260809362008FEF82BB57
-:1002C00011BA80916200806880936200CE010E9422
-:1002D0005A0082E08A95F1F700C080916200816047
-:1002E0008093620080916200D7FD0BC08260809392
-:1002F000620082E08A95F1F700C080B3DF91CF9170
-:1003000008958D7F80936200F4CF1F920F920FB6F5
-:100310000F9211242F933F934F935F936F937F938B
-:100320008F939F93AF93BF93EF93FF935F9B05C012
-:100330008CB10E9490025F99FBCFFF91EF91BF912A
-:10034000AF919F918F917F916F915F914F913F916D
-:100350002F910F900FBE0F901F901895CF93DF93A2
-:1003600064E070E082E10E945102C69A1BBA15BA9D
-:10037000C2E6D0E088818061888382E08A95F1F7C7
-:1003800000C081B182FB882780F90E9479021BBAE4
-:1003900084E085BB88818061888382E08A95F1F75B
-:1003A00000C081B182FB882780F90E9479021BBAC4
-:1003B00088E085BB88818061888382E08A95F1F737
-:1003C00000C081B182FB882780F90E9479021BBAA4
-:1003D0008CE085BB88818061888382E08A95F1F713
-:1003E00000C081B182FB882780F90E9479021BBA84
-:1003F00015BA888180618883DF91CF91089581E06B
-:1004000089B91092900088E98AB9E5E9F0E0808125
-:100410008660808308955D9BFECF8CB90895982FE8
-:1004200092959F709A3070F4905D8F708A3040F48E
-:10043000805D5D9BFECF9CB95D9BFECF8CB908951E
-:10044000895CF7CF995CF1CFFC019081992339F059
-:1004500031965D9BFECF9CB991919111FACF089591
-:10046000411551056105710551F0FC01480F591FF7
-:1004700081915D9BFECF8CB9E417F507C9F708950C
-:1004800090910801382F28E05CE8492F4327969582
-:1004900040FD952736952150C1F7909308010C94A3
-:1004A0000B021F93CF93DF93182FEB0110920801DB
-:1004B00086E40E944002812F0E9440028C2F0E94FD
-:1004C00040028D2F0E944002D0930701C093060185
-:1004D0001092050110920401CD2B21F0DF91CF91F4
-:1004E0001F91089580910801DF91CF911F910C9485
-:1004F0000B020E9440028091040190910501019637
-:100500009093050180930401209106013091070129
-:100510008217930709F00895809108010C940B024B
-:1005200090910001992319F0863409F008951092F2
-:10053000000160910201709103016115710559F18B
-:1005400090910101382F28E05CE8432F49279695C8
-:1005500040FD952736952150C1F7909301016130F8
-:10056000710509F447C0DCF062307105E9F16330D0
-:10057000710539F52091090130910A01A901582B23
-:1005800050930A01409309016F5F7F4F70930301FD
-:1005900060930201089510920B0190E0D3CF611592
-:1005A000710579F4863481F381E08093000160E085
-:1005B00070E082E00E94510260910201709103019B
-:1005C000E3CF9B01245031092A3154E0350738F537
-:1005D0004091090150910A012417350770F4F9017F
-:1005E000E35FFE4F8083D0CF90E090930A01809329
-:1005F0000901CACF80930C01C7CF409109015091E6
-:100600000A012417350709F0BFCF81E0911113C00B
-:1006100080930B0110920301109202010895109231
-:1006200003011092020181E08093000160E070E01C
-:1006300084E00C9451028093000160E070E083E05C
-:100640000E945102E7CF1092030110920201109212
-:100650000B0110920001089578940E94FF0187B366
-:10066000806C87BB87EB809361008FEF8093620083
-:1006700012981A9A82BB11BA1BBA15BA90916200ED
-:100680009061909362008ABB84BBBC98C498C79861
-:10069000C6980E94230360E070E080E00E9451024F
-:1006A000BEE6AB2EB12C8FB589628FBD8EB5816051
-:1006B0008EBD20E030E0E0E041E050E060E070E03E
-:1006C00080910B01811138C08FB589628FBD8EB5C5
-:1006D00081608EBD403187E258076105710508F4DD
-:1006E00061C0E11164C0C90101968E3691050CF418
-:1006F00066C0E1E09C012456310939BD28BD9C014A
-:10070000C501821B930B853191050CF06AC08B30BB
-:1007100091052CF044E150E0481B590BCA01880FA9
-:10072000991F909379008093780040E050E0BA01DF
-:1007300080910B01882341F210920B0110927900F5
-:100740001092780019BC18BC1FBC80910C01893133
-:1007500009F4C2C408F049C08B3009F49EC408F4FF
-:10076000B6C1813109F4F3C308F0EBC18D3009F44F
-:100770002DC58F3009F097CF3091620031603093F2
-:100780006200209162002E7F2093620080E890E05A
-:100790002BBB3BBB0197E1F760E070E080E10E947A
-:1007A000510281CF4F5F5F4F6F4F7F4F89CF2150F5
-:1007B000310989F4E0E040E050E0BA0181CF8436AD
-:1007C000910524F02356310939BD28BD9C0140E034
-:1007D00050E0BA0175CF243631050CF491CFC90130
-:1007E00089CF40E050E0BA016BCF843209F4B2C344
-:1007F00008F408C1873209F497C208F096C185321F
-:1008000009F419C3863209F04ECF80900D01809112
-:100810000E01912C982A00910F018091100110E097
-:10082000182BC79A80916200826080936200011544
-:10083000110509F4C9C141E1C42E41E0D42E94014F
-:10084000207E1601F601E401712C06C0CE01807EE7
-:100850002817390709F040C081918F3F09F0739440
-:100860002196015011096F0189F7772009F4ACC175
-:1008700060EF80E090E80E94FC006AEA8AEA9AE869
-:100880000E94FC0065E585E595E80E94FC0065E2B4
-:1008900080E090E80E94FC007A94672D80E090E868
-:1008A0000E94FC00F10161911F016F3F89F074010A
-:1008B0006894F7F8C7010E94FC00FFEF8F1A9F0AA7
-:1008C000772071F07A94F10161911F016F3F79F700
-:1008D0002FEF821A920AE6CF7110CACF4E01AFCF26
-:1008E00069E280E090E80E94FC002AE12A95F1F795
-:1008F00000C030EA432E36E8532E66246394712CF0
-:10090000912C41E0241A31080CC0FAE1FA95F1F774
-:1009100000C021E0421A510861087108982E09F4BC
-:100920006AC0C7010E945101909162009260909349
-:1009300062008911EACFF10190819911E6CF01158A
-:10094000110509F441C14E017ACF00910D0180914A
-:100950000E0110E0182BE0900F0180911001F12C96
-:10096000F82AC79A17FD9DC4E114F10409F4B3C134
-:1009700081E1882E81E0982EF40171904F0160EFA3
-:1009800080E090E00E94A3006AEA85E595E00E947D
-:10099000A30065E58AEA92E00E94A30060EA85E58B
-:1009A00095E00E94A300672DC8010E94A300E80102
-:1009B000D068C12CD12C09C087EC90E00197F1F7E9
-:1009C00000C000009FEFC91AD90ACE010E946A0038
-:1009D000781609F463C1EAE0CE16D10469F71BBAB0
-:1009E00015BA8091620080618093620080916200FC
-:1009F0008E7F8093620080916200826080936200AB
-:100A0000C79851CE8B3109F4A0CF08F4F3C08232DD
-:100A100009F46AC2833209F046CEC79AC49AC39ACF
-:100A2000BC9ABB9A8091620082608093620060EF02
-:100A300080E090E00E94CB006AEA8AEA9AE00E9495
-:100A4000CB0065E585E595E00E94CB0060E88AEA89
-:100A50009AE00E94CB006AEA8AEA9AE00E94CB0000
-:100A600065E585E595E00E94CB0060E380E090E0DD
-:100A70000E94CB00C0E0D0E00BC0C83BFBE0DF072A
-:100A800069F0EFECF7E03197F1F700C00000219634
-:100A900080E090E80E9487008F3F79F71BBA15BA73
-:100AA0008091620080618093620080916200826028
-:100AB00080936200BC98C498C798C83BDB4009F497
-:100AC000F2CD60E070E08AE00E945102ECCD863009
-:100AD00009F48AC008F47FC0873009F47CC18930EA
-:100AE00009F0E1CDE0900D0180910E01F12CF82A82
-:100AF000C0910F0180911001D0E0D82BC79A2097A8
-:100B000069F001E111E0F80161918F01C7010E94D4
-:100B1000FC00FFEFEF1AFF0A2197A9F7C79860E0E2
-:100B200070E08AE00E945102BECD883209F46DC3A4
-:100B30008E3F09F0B8CDF89414BEE0E0F8EF0995C7
-:100B4000B2CD833109F4CEC0883109F0ACCDC79A5B
-:100B500060EF80E090E80E94FC006AEA8AEA9AE886
-:100B60000E94FC0065E585E595E80E94FC0060E8D0
-:100B70008AEA9AE80E94FC006AEA8AEA9AE80E94F5
-:100B8000FC0065E585E595E80E94FC0060E18AEAE5
-:100B90009AE80E94FC0006C08FEC97E00197F1F7FD
-:100BA00000C0000080E090E80E9451018F3FA1F753
-:100BB0001BBA15BA809162008061809362008091B7
-:100BC0006200816080936200809162008260809305
-:100BD0006200C798A4CF853009F065CD60E070E071
-:100BE00080E00E9451025FCD60E070E081E00E94F1
-:100BF000510259CDC79A60EF80E090E00E94A300B7
-:100C00006AEA85E595E00E94A30065E58AEA92E03C
-:100C10000E94A30060E885E595E00E94A3006AEACF
-:100C200085E595E00E94A30065E58AEA92E00E94CE
-:100C3000A30060E185E595E00E94A300C0E0D0E05C
-:100C40000BC0C03197E2D90769F08FEC97E00197AC
-:100C5000F1F700C00000219680E090E00E946A0059
-:100C60008F3F79F71BBA15BA80916200806180933B
-:100C700062008091620081608093620080916200D6
-:100C8000826080936200C798C031D74209F40BCDCF
-:100C900060E070E08EE00E94510205CD1BBA15BAEB
-:100CA00080916200806180936200809162008E7FFB
-:100CB0008093620080916200826080936200FAE01B
-:100CC000CF16D10409F49CCE0F5F1F4F21E0E21A2A
-:100CD000F10809F051CEC79860E070E08EE00E9404
-:100CE0005102E1CCC79AC69A809162008E7F8093B0
-:100CF0006200809162008260809362002FEF40E783
-:100D000052E0215040405040E1F700C00000809187
-:100D10006200816080936200C798C69860E070E0CE
-:100D200084E10E945102BFCCC0910D0180910E015F
-:100D3000D0E0D82B00910F018091100110E0182B0A
-:100D4000C69ACE010E9451010115110509F4B4C2E1
-:100D500080E090E0CBBBD5BBF2E0FA95F1F700C0A4
-:100D600020B3822728E030E009C09695879541E0BE
-:100D7000842740EA94272150310939F080FDF5CFCE
-:100D80009695879521503109C9F70150110921968F
-:100D900001151105F9F6D82FC92F1BBA15BA809184
-:100DA0006200806180936200809162008160809324
-:100DB00062008091620082608093620062E070E075
-:100DC00088E00E9451028D2F0E9479028C2F0E9490
-:100DD0007902C69868CC00910D0180910E0110E057
-:100DE000182BC0910F0180911001D0E0D82BC69A2A
-:100DF000BE0188E00E945102209751F0C8010E9474
-:100E000051010E94790221970F5F1F4F2097B1F780
-:100E10001BBA15BA80916200806180936200809154
-:100E200062008160809362008091620082608093A2
-:100E30006200C69838CCC79A60EF80E090E80E94C4
-:100E4000FC006AEA8AEA9AE80E94FC0065E585E50A
-:100E500095E80E94FC0060E88AEA9AE80E94FC009B
-:100E60006AEA8AEA9AE80E94FC0065E585E595E869
-:100E70000E94FC0060E380E090E80E94FC00C0E07B
-:100E8000D0E010C0C83B9BE0D90791F08091620090
-:100E90008260809362008FEC97E00197F1F700C0C9
-:100EA0000000219680E090E80E9451018F3F51F7A9
-:100EB0001BBA15BA809162008061809362008091B4
-:100EC0006200816080936200809162008260809302
-:100ED0006200C798C83BDB4009F4E5CB60E070E0F6
-:100EE0008AE00E945102DFCB00910D0180910E013A
-:100EF00010E0182BC0910F0180911001D0E0D82B89
-:100F0000C69AC49AC39ABC9ABB9ABE0188E00E9452
-:100F10005102209751F0C8010E9487000E94790277
-:100F200021970F5F1F4F2097B1F71BBA15BA809119
-:100F30006200806180936200809162008260809391
-:100F40006200C49AC39ABC98C498C698ACCB0E945D
-:100F5000AE01A9CBE0900D0180910E01F12CF82A91
-:100F600000910F018091100110E0182BC79AC49ACC
-:100F7000C39ABC9ABB9A809162008260809362009F
-:100F80000115110509F480C061E1C62E61E0D62E7D
-:100F90009701207E4601F601E701712C05C0CE01C4
-:100FA000807E28173907C1F581918F3F09F073942E
-:100FB0002196015011096F0191F7772009F464C05F
-:100FC0006AEA8AEA9AE00E94CB0065E585E595E049
-:100FD0000E94CB0065E280E090E00E94CB007A9412
-:100FE000672D80E090E00E94CB00F40161914F01F9
-:100FF0006F3F71F0C7010E94CB00C70101967720B7
-:1010000079F07C017A94F40161914F016F3F91F77F
-:10101000FFEFEF1AFF0AE9CF7110D2CF7E01B8CFF0
-:1010200069E280E090E00E94CB00FAE1FA95F1F7E6
-:1010300000C06894F7F850EA452E56E8552E66240D
-:101040006394712C312C21E0821A91080CC0FAE1D2
-:10105000FA95F1F700C021E0421A510861087108C1
-:10106000382E09F420C1C7010E94870090916200C8
-:101070009260909362008311EACFF4019081931102
-:10108000E6CF0115110551F68091620082608093D0
-:101090006200BC98C498C79842CD00910D01809120
-:1010A0000E0110E0182BC0910F0180911001D0E0CB
-:1010B000D82BC69ABE018CE00E945102209709F4F9
-:1010C000A7CEC8010E946A000E94790221970F5F93
-:1010D0001F4F2097B1F79CCEE0900D0180910E013B
-:1010E000F12CF82A00910F018091100110E0182BCB
-:1010F000C79A0115110509F411CD71E1872E71E030
-:10110000972EF40161904F0160EF80E090E80E941B
-:10111000FC006AEA85E595E80E94FC0065E58AEA3C
-:1011200092E80E94FC0060EA85E595E80E94FC00D8
-:10113000E701D068662DCE010E94FC00F5E8FA9523
-:10114000F1F70000C12CD12C712C0CC025E82A9598
-:10115000F1F700004FEFC41AD40A782E58ECC516E8
-:10116000D10431F1CE010E94510190916200926050
-:10117000909362008711EACF6710E8CF80916200F8
-:101180008260809362001BBA15BA80916200806110
-:10119000809362008AE0C816D1040CF031CC9FEF36
-:1011A000E91AF90A0150110909F0ABCFC798B7CC79
-:1011B000809162008260809362001BBA15BA8091B0
-:1011C0006200806180936200C7986DCAE0900D0153
-:1011D00080910E01F12CF82AC0910F01809110012D
-:1011E000D0E0D82BC79A209709F475CD01E111E022
-:1011F000F80161918F01C7010E94A300FFEFEF1A70
-:10120000FF0A2197A9F7C79867CDE0900D0180915B
-:101210000E01F12CF82A00910F018091100110E0CD
-:10122000182BC69A0115110509F449C0C0E0D0E099
-:10123000C7010E946A00C82788E090E04C2FD6952D
-:10124000C79540FF04C051E0C52750EAD527019754
-:10125000A9F7015011098FEFE81AF80A01151105D5
-:1012600039F71C2FCD2F1BBA15BA8091620080610F
-:10127000809362008091620081608093620080911F
-:10128000620082608093620062E070E08CE00E9405
-:101290005102812F0E9479028C2F0E947902C698F8
-:1012A00002CA105861CB8091620082608093620014
-:1012B000BC98C498C798F7C9C0E0D0E06ECDC0E034
-:0812C00010E0D1CFF894FFCF3C
+:1000A0001D92A732B207E1F70E94CE040C94BF1054
+:1000B0000C940000C49AC39AE2E6F0E0808182606A
+:1000C000808380818068808325E52BBB85E085BBAC
+:1000D0008081806180839FEF91BB22BB80818160A2
+:1000E000808380818D7F808382E08A95F1F700C0D4
+:1000F000C39882E08A95F1F700C0C39A1BBA15BA7B
+:1001000080818061808380818260808392BB11BA0C
+:100110000895E2E6F0E090819E7F90839081926066
+:1001200090832FEF21BB90819F77908382BB1BBA76
+:1001300080E885BB80818061808382E08A95F1F7C9
+:1001400000C080818160808380818D7F808382E098
+:100150008A95F1F700C080818E7F808380818260E4
+:10016000808382E08A95F1F700C080818068808377
+:1001700022BB11BA1BBA15BA80818061808380814D
+:10018000816080830895C49AC39AE2E6F0E090818A
+:10019000926090839081906890831BBA15BA908189
+:1001A000906190839FEF91BB82BB8081816080834F
+:1001B00080818D7F808382E08A95F1F700C0C398AB
+:1001C00082E08A95F1F700C0C39A1BBA15BA808104
+:1001D0008061808380818260808392BB11BA0895A0
+:1001E000C49AC39AE2E6F0E0908192609083908195
+:1001F000906890839AEA9BBB9AE095BB908190614E
+:1002000090839FEF91BB82BB8081816080838081DE
+:100210008D7F808382E08A95F1F700C0C39882E0E9
+:100220008A95F1F700C0C39A1BBA15BA8081806124
+:10023000808380818260808392BB11BA0895E2E658
+:10024000F0E090819E7F90839081926090832FEF69
+:1002500021BB90819F77908382BB8AEA8BBB8AE81F
+:1002600085BB80818061808382E08A95F1F700C040
+:1002700080818160808380818D7F808382E08A9508
+:10028000F1F700C080818E7F8083808182608083CF
+:1002900082E08A95F1F700C080818068808322BB6C
+:1002A00011BA1BBA15BA8081806180838081816018
+:1002B00080830895E2E6F0E090819E7F90839081B4
+:1002C000926090832FEF21BB90819F77908382BBB8
+:1002D00085E58BBB85E885BB80818061808382E07A
+:1002E0008A95F1F700C080818160808380818D7F55
+:1002F000808382E08A95F1F700C080818E7F8083C1
+:1003000080818260808382E08A95F1F700C08081DD
+:100310008068808322BB11BA1BBA15BA80818061C4
+:1003200080838081816080830895209162002E7F88
+:1003300020936200209162002260209362002FEFE0
+:1003400021BB209162002F772093620062BB8BBBA0
+:1003500095BB2091620095FD3AC020612093620018
+:1003600022E02A95F1F700C02091620021602093DD
+:10037000620097FD30C080916200826080936200CD
+:1003800082E08A95F1F700C0809162008E7F8093B1
+:1003900062008091620082608093620022E02A9570
+:1003A000F1F700C0809162008068809362008FEF57
+:1003B00082BB11BA1BBA15BA80916200806180932A
+:1003C00062008091620081608093620008952F7EB8
+:1003D00020936200C5CF809162008D7F8093620080
+:1003E000CFCF1F920F920FB60F9211242F933F93EE
+:1003F0004F935F936F937F938F939F93AF93BF932D
+:10040000EF93FF935F9B05C08CB10E94FC035F9943
+:10041000FBCFFF91EF91BF91AF919F918F917F9112
+:100420006F915F914F913F912F910F900FBE0F9061
+:100430001F901895CF93DF9364E070E082E10E94F3
+:10044000AC02C69A1BBA15BAC2E6D0E088818061B8
+:10045000888382E08A95F1F700C081B182FB88270A
+:1004600080F90E94A1031BBA84E085BB888180616A
+:10047000888382E08A95F1F700C081B182FB8827EA
+:1004800080F90E94A1031BBA88E085BB8881806146
+:10049000888382E08A95F1F700C081B182FB8827CA
+:1004A00080F90E94A1031BBA8CE085BB8881806122
+:1004B000888382E08A95F1F700C081B182FB8827AA
+:1004C00080F90E94A1031BBA15BA888180618883D4
+:1004D000DF91CF91089581E089B91092900088E969
+:1004E0008AB9E5E9F0E080818660808308955D9BAC
+:1004F000FECF8CB90895982F92959F709A3070F422
+:10050000905D8F708A3040F4805D5D9BFECF9CB91A
+:100510005D9BFECF8CB90895895CF7CF995CF1CFD4
+:10052000FC019081992339F031965D9BFECF9CB9F7
+:1005300091919111FACF0895411551056105710509
+:1005400051F0FC01480F591F81915D9BFECF8CB982
+:10055000E417F507C9F708951F93CF93DF93182F7A
+:10056000EB018BE98093080186E40E947702809179
+:100570000801982F9695812780FF02C08CE8982764
+:10058000812F8695292F2695982790FF02C09CE8F9
+:1005900029278695922F9695282720FF02C02CE8C0
+:1005A00092278695292F2695982790FF02C09CE8D0
+:1005B00029278695922F9695282720FF02C02CE8A0
+:1005C00092278695292F2695982790FF02C09CE8B0
+:1005D00029278695922F9695282720FF02C02CE880
+:1005E0009227292F269586959170981711F08CE8FF
+:1005F000282720930801812F0E947702809108010B
+:10060000982F96958C2780FF02C08CE898278C2F16
+:100610008695292F2695982790FF02C09CE82927C8
+:100620008695922F9695282720FF02C02CE89227C6
+:100630008695292F2695982790FF02C09CE82927A8
+:100640008695922F9695282720FF02C02CE89227A6
+:100650008695292F2695982790FF02C09CE8292788
+:100660008695922F9695282720FF02C02CE8922786
+:10067000292F269586959170981711F08CE82827D8
+:10068000209308018C2F0E94770280910801982FF7
+:1006900096958D2780FF02C08CE898278D2F869530
+:1006A000292F2695982790FF02C09CE82927869538
+:1006B000922F9695282720FF02C02CE89227869536
+:1006C000292F2695982790FF02C09CE82927869518
+:1006D000922F9695282720FF02C02CE89227869516
+:1006E000292F2695982790FF02C09CE829278695F8
+:1006F000922F9695282720FF02C02CE89227292FB9
+:10070000269586959170981711F08CE828272093EC
+:1007100008018D2F0E947702D0930701C093060134
+:100720001092050110920401CD2B21F0DF91CF91A1
+:100730001F91089580910801DF91CF911F910C9432
+:10074000770290910801292F2695982790FF02C0E3
+:100750009CE82927982F9695322F3695292720FF38
+:1007600002C02CE832279695232F2695392730FF93
+:1007700002C03CE823279695322F3695292720FF83
+:1007800002C02CE832279695232F2695392730FF73
+:1007900002C03CE823279695322F3695292720FF63
+:1007A00002C02CE832279695232F2695392730FF53
+:1007B00002C03CE82327322F3695969521702917E1
+:1007C00011F09CE83927309308010E94770280914C
+:1007D0000401909105010196909305018093040115
+:1007E00020910601309107018217930709F00895BF
+:1007F000809108010C94770290910001992319F0DF
+:10080000863409F008951092000120910201309180
+:1008100003012115310509F460C090910101492FB0
+:100820004695982790FF02C09CE84927982F9695F7
+:10083000542F5695492740FF02C04CE854279695FF
+:10084000452F4695592750FF02C05CE845279695ED
+:10085000542F5695492740FF02C04CE854279695DF
+:10086000452F4695592750FF02C05CE845279695CD
+:10087000542F5695492740FF02C04CE854279695BF
+:10088000452F4695592750FF02C05CE84527542F55
+:10089000569596954170491711F09CE85927509349
+:1008A00001012130310509F447C0DCF02230310567
+:1008B000E9F12330310539F54091090150910A01E0
+:1008C000BA01782B70930A01609309012F5F3F4FA3
+:1008D0003093030120930201089510920B0190E0E0
+:1008E0009ECF2115310579F4863481F381E0809320
+:1008F000000160E070E082E00E94AC022091020101
+:1009000030910301E3CFB901645071096A3194E079
+:10091000790738F5E0910901F0910A016E177F0718
+:1009200070F4FB01E35FFE4F8083D0CF90E09093A3
+:100930000A0180930901CACF80930C01C7CF80912F
+:10094000090190910A016817790709F0BFCF81E08A
+:10095000511113C080930B011092030110920201F8
+:100960000895109203011092020181E0809300012A
+:1009700060E070E084E00C94AC028093000160E0E1
+:1009800070E083E00E94AC02E7CF10920301109266
+:10099000020110920B0110920001089578940E94B8
+:1009A0006B0287B3806C87BB87EB809361008FEF0E
+:1009B0008093620012981A9A82BB11BA1BBA15BAB8
+:1009C000909162009061909362008ABB84BBBC9856
+:1009D000C498C798C6980E94C50460E070E080E0A3
+:1009E0000E94AC02DEE68D2E912C14E1212E312CDA
+:1009F00077247A948FB589628FBD8EB581608EBD64
+:100A000020E030E0E0E041E050E060E070E0809124
+:100A10000B01811137C08FB589628FBD8EB58160A2
+:100A20008EBD403187E258076105710508F463C047
+:100A3000E11166C0C90101968E3691050CF468C0BB
+:100A4000E1E09C012456310939BD28BD9C01C40157
+:100A5000821B930B853191050CF06CC08B30910596
+:100A600024F0E101C81BD90BCE01880F991F909388
+:100A700079008093780040E050E0BA0180910B014A
+:100A8000882349F210920B0110927900109278009D
+:100A900019BC18BC1FBC80910C01893111F40C9455
+:100AA000AE0E08F04BC08B3011F40C94630E08F4BA
+:100AB00019C3813109F4D4C708F04FC38D3011F444
+:100AC0000C94800F8F3009F095CF30916200316027
+:100AD00030936200209162002E7F2093620080E8B4
+:100AE00090E02BBB3BBB0197E1F760E070E080E159
+:100AF0000E94AC027FCF4F5F5F4F6F4F7F4F87CF1A
+:100B00002150310989F4E0E040E050E0BA017FCFA4
+:100B10008436910524F02356310939BD28BD9C0146
+:100B200040E050E0BA0173CF243631050CF48FCF8A
+:100B3000C90187CF40E050E0BA0169CF843209F49F
+:100B400093C708F45DC2873209F496C508F0F9C26C
+:100B5000853209F4BCC6863209F04CCFC0900D0135
+:100B600080910E01D12CD82A00910F0180911001A3
+:100B700010E0182BC79A8091620082608093620017
+:100B80000115110509F442C3C1E1EC2EC1E0FC2EB0
+:100B90009601207E5701F701E601612C05C0CE01C8
+:100BA000807E28173907B1F581918F3F09F0639452
+:100BB0002196015011097F0191F7662009F426C39F
+:100BC00080EF0E9489008AEA0E941F0185E50E9449
+:100BD0005A0185E20E9489006A94862D0E9489004C
+:100BE000F50161915F016F3F89F02601689457F824
+:100BF000C2010E949501C6010196662079F06C0140
+:100C00006A94F50161915F016F3F79F72FEFC21A86
+:100C1000D20AE6CF6110D4CF6E01BACF89E20E942A
+:100C20008900FAE1FA95F1F700C0942D252D40EAEC
+:100C300056E861E070E030E0F5013197D5FE0CC078
+:100C40004DC03AE13A95F1F700C0415051096109B0
+:100C500071093A2F09F4CDC1809162008E7F809393
+:100C600062008091620082608093620072BA11BA61
+:100C7000809162008068809362009BBB25BB80915D
+:100C80006200806180936200809162008160809345
+:100C90006200809162008D7F8093620082E08A957D
+:100CA000F1F700C0A0B3809162008260809362007F
+:100CB0003A13C7CF8081A813C4CF0115110509F4D9
+:100CC000A5C26E0165CF3AE13A95F1F700C04150F7
+:100CD0005109610971093A2F09F48BC180916200B1
+:100CE0008E7F8093620080916200826080936200B8
+:100CF00072BA11BA809162008068809362009BBBD7
+:100D000025BB809162008F7E80936200809162009B
+:100D1000816080936200809162008D7F8093620089
+:100D200082E08A95F1F700C0A0B3809162008260F2
+:100D300080936200A313C7CF80818313C4CFBDCF3C
+:100D400040910D0180910E0150E0582B60910F01F0
+:100D50008091100170E0782BC79A57FF02C00C9465
+:100D6000A8106115710509F45EC4E1E1F1E080EFBE
+:100D7000E82E1AEAA5E5B5E092E0F92E00EA3191F5
+:100D8000809162008E7F8093620080916200826019
+:100D90008093620071BAE2BA1BBA15BA8091620000
+:100DA000806180936200809162008B7F80936200FB
+:100DB00022E02A95F1F700C0809162008460809360
+:100DC000620072BA11BA1BBA15BA809162008061D2
+:100DD00080936200809162008160809362008091C4
+:100DE00062008E7F809362008091620082608093B7
+:100DF000620071BA12BBABBBB5BB8091620080616F
+:100E000080936200809162008B7F8093620082E019
+:100E10008A95F1F700C0809162008460809362003F
+:100E200072BA11BA1BBA15BA8091620080618093C0
+:100E30006200809162008160809362008091620014
+:100E40008E7F809362008091620082608093620056
+:100E500071BAA2BB1BBBF5BA80916200806180931E
+:100E60006200809162008B7F8093620092E09A958D
+:100E7000F1F700C08091620084608093620072BAD2
+:100E800011BA1BBA15BA809162008061809362002A
+:100E900080916200816080936200809162008E7F09
+:100EA000809362008091620082608093620071BAD8
+:100EB00002BBABBBB5BB80916200806180936200D6
+:100EC000809162008B7F80936200C2E0CA95F1F747
+:100ED00000C08091620084608093620072BA11BA8F
+:100EE0001BBA15BA80916200806180936200809184
+:100EF0006200816080936200809162008E7F8093A7
+:100F000062008091620082608093620071BA32BB9D
+:100F10004BBB55BBEA01CC27D0728091620055FDD6
+:100F200064C3806180936200809162008B7F8093B4
+:100F3000620022E02A95F1F700C08091620084608F
+:100F40008093620072BA11BA1BBA15BA809162001E
+:100F50008061809362008091620081608093620072
+:100F6000CA019068D82EC92E80E090E0CD2B41F0C8
+:100F70000FC3C7ECD0E02197F1F700C00000019645
+:100F8000209162002E7F20936200209162002260F7
+:100F90002093620072BA11BADBBAC5BA209162001E
+:100FA000206120936200209162002F7D20936200D7
+:100FB000C2E0CA95F1F700C0C0B320916200206280
+:100FC00020936200209162002160209362003C1710
+:100FD00009F40FC38A30910561F61BBA15BA8091E6
+:100FE0006200806180936200809162008E7F8093B6
+:100FF000620080916200826080936200C798FACCA0
+:101000008B3109F49DCE08F417C1823209F4CFC4A4
+:10101000833209F0EFCCC79AC49AC39ABC9ABB9AA0
+:101020008091620082608093620080EF0E94C30022
+:101030008AEA0E94F0000E945A0080E80E94F000B4
+:101040008AEA0E94F0000E945A0080E30E94C300D6
+:1010500020E030E090E80CC0283B4BE0340749F139
+:10106000EFECF7E03197F1F700C000002F5F3F4F42
+:1010700072BA11BA809162008068809362001BBAD4
+:1010800095BB8091620080618093620080916200D4
+:10109000816080936200809162008D7F8093620006
+:1010A000C39AC498F2E0FA95F1F700C080B38F3F7D
+:1010B00099F61BBA15BA8091620080618093620034
+:1010C00080916200826080936200BC98C498C79847
+:1010D000283B3B4009F48ECC60E070E08AE00E943F
+:1010E000AC0288CC863009F4A1C008F496C08730E1
+:1010F00009F48EC3893009F07DCC00910D018091F7
+:101100000E0110E0182BC0910F0180911001D0E06A
+:10111000D82BC79A209771F091E1E92E91E0F92E32
+:10112000F70161917F01C8010E9495010F5F1F4F78
+:101130002197B1F7C79860E070E08AE00E94AC02A6
+:1011400059CC883209F42BC78E3F09F053CCF89460
+:1011500014BEE0E0F8EF09954DCC833109F46AC282
+:10116000883109F047CCC79A80EF0E9489008AEA4B
+:101170000E941F0185E50E945A0180E80E941F011C
+:101180008AEA0E941F0185E50E945A0180E10E94BF
+:101190001F0190E806C0CFECD7E02197F1F700C01F
+:1011A0000000809162008E7F8093620080916200D7
+:1011B00082608093620072BA11BA80916200806886
+:1011C000809362001BBA95BB80916200806180931E
+:1011D0006200809162008160809362008091620071
+:1011E0008D7F80936200D2E0DA95F1F700C080B382
+:1011F0008F3F89F61BBA15BA809162008061809397
+:101200006200809162008160809362008091620040
+:10121000826080936200C7988ECF853009F0EACB58
+:1012200060E070E080E00E94AC02E4CB60E070E03F
+:1012300081E00E94AC02DECBC79A809162008E7F73
+:10124000809362008091620082608093620071BA34
+:1012500080EF82BB1BBA15BA8091620080618093D7
+:101260006200809162008B7F8093620032E03A9549
+:10127000F1F700C08091620084608093620072BACE
+:1012800011BA1BBA15BA8091620080618093620026
+:1012900080916200816080936200809162008E7F05
+:1012A000809362008091620082608093620071BAD4
+:1012B0002AEA22BB85E58BBB95E095BB30916200A5
+:1012C000306130936200309162003B7F3093620066
+:1012D00042E04A95F1F700C03091620034603093EB
+:1012E000620072BA11BA1BBA15BA3091620030614D
+:1012F000309362003091620031603093620030912F
+:1013000062003E7F30936200309162003260309321
+:10131000620071BA82BB2BBB42E045BB30916200D8
+:10132000306130936200309162003B7F3093620005
+:1013300052E05A95F1F700C030916200346030936A
+:10134000620072BA11BA1BBA15BA309162003061EC
+:1013500030936200309162003160309362003091CE
+:1013600062003E7F309362003091620032603093C1
+:10137000620071BA30E832BB8BBB95BB3091620022
+:10138000306130936200309162003B7F30936200A5
+:1013900062E06A95F1F700C03091620034603093EA
+:1013A000620072BA11BA1BBA15BA3091620030618C
+:1013B000309362003091620031603093620030916E
+:1013C00062003E7F30936200309162003260309361
+:1013D000620071BA22BB8BBB95BB30916200306159
+:1013E00030936200309162003B7F30936200C2E034
+:1013F000CA95F1F700C0309162003460309362000A
+:1014000072BA11BA1BBA15BA3091620030613093CA
+:10141000620030916200316030936200309162006E
+:101420003E7F309362003091620032603093620000
+:1014300071BA82BB2BBB45BB209162002061209317
+:101440006200209162002B7F20936200D2E0DA9547
+:10145000F1F700C02091620024602093620072BA0C
+:1014600011BA1BBA15BA2091620020612093620064
+:1014700020916200216020936200209162002E7F03
+:10148000209362002091620022602093620071BA72
+:1014900020E122BB8BBB95BB809162008061809371
+:1014A0006200809162008B7F80936200E2E0EA95A7
+:1014B000F1F700C08091620084608093620072BA8C
+:1014C00011BA1BBA15BA80916200806180936200E4
+:1014D0008091620081608093620020E030E00CC067
+:1014E0002031C7E23C0789F18FEC97E00197F1F7D3
+:1014F00000C000002F5F3F4F809162008E7F80937D
+:1015000062008091620082608093620072BA11BAB8
+:101510001BBA15BA8091620080618093620080914D
+:1015200062008F7D8093620092E09A95F1F700C08F
+:1015300090B380916200806280936200809162002B
+:101540008160809362009F3F59F61BBA15BA809163
+:10155000620080618093620080916200816080936C
+:10156000620080916200826080936200C79820319F
+:10157000374209F43FCA60E070E08EE00E94AC029E
+:1015800039CAC7ECD0E02197F1F700C000000196FE
+:10159000209162002E7F20936200209162002260E1
+:1015A0002093620072BA11BADBBAC5BA2091620008
+:1015B0002F7E20936200209162002F7D2093620095
+:1015C000D2E0DA95F1F700C0C0B32091620020624A
+:1015D00020936200209162002160209362003C17FA
+:1015E00041F08A30910569F6F8CC8F7E80936200D5
+:1015F0009BCC1BBA15BA2091620020612093620037
+:10160000209162002E7F2093620020916200226070
+:10161000209362000A9709F4F1CC4F5F5F4F61504D
+:10162000710909F0ACCBC79860E070E08EE00E94D1
+:10163000AC02E0C9C79AC69A809162008E7F8093FF
+:101640006200809162008260809362004FEF50E7F9
+:1016500062E0415050406040E1F700C000008091DE
+:101660006200816080936200C798C69860E070E075
+:1016700084E10E94AC02BEC920910D0180910E014F
+:1016800030E0382B40910F018091100150E0582B31
+:10169000C69A809162008E7F809362008091620082
+:1016A00082608093620072BA11BA80916200806891
+:1016B000809362002BBB35BB8091620035FD44C531
+:1016C00080618093620080916200816080936200FB
+:1016D0008091620037FD4CC582608093620062E0B9
+:1016E0006A95F1F700C080B34115510509F43DC575
+:1016F00080E090E026C09695879580FD34C0969551
+:10170000879580FD38C09695879580FD3CC096955D
+:10171000879580FD40C09695879580FD44C096953D
+:10172000879580FD48C09695879580FD4CC096951D
+:101730008795415051092F5F3F4F4115510509F4DD
+:1017400050C02BBB35BBC2E0CA95F1F700C060B3F7
+:10175000862780FFD0CF96958795D1E08D27D0EA58
+:101760009D2780FFCCCF96958795E1E08E27E0EA14
+:101770009E2780FFC8CF96958795F1E08F27F0EAE6
+:101780009F2780FFC4CF9695879561E0862760EA02
+:10179000962780FFC0CF96958795C1E08C27C0EA39
+:1017A0009C2780FFBCCF96958795D1E08D27D0EA06
+:1017B0009D2780FFB8CF96958795E1E08E27E0EAD8
+:1017C0009E2780FFB4CF96958795F1E08F27F0EAAA
+:1017D0009F27415051092F5F3F4F4115510509F097
+:1017E000B0CFD82FC92F1BBA15BA80916200806183
+:1017F000809362008091620081608093620080919A
+:10180000620082608093620062E070E088E089C4D8
+:10181000C0910D0180910E01D0E0D82B00910F01F5
+:101820008091100110E0182BC69AB80188E00E9440
+:10183000AC0201151105E9F437C0806180936200A4
+:101840008091620081608093620080916200D7FD88
+:1018500077C482608093620022E02A95F1F700C08D
+:1018600080B30E94A10301501109219601151105B1
+:10187000D9F0809162008E7F809362008091620037
+:1018800082608093620072BA11BA809162008068AF
+:1018900080936200CBBBD5BB80916200D5FFCDCFDA
+:1018A0008F7E80936200CCCF1BBA15BA8091620004
+:1018B0008061809362008091620081608093620009
+:1018C00080916200826080936200C69893C8C79A34
+:1018D00080EF0E9489008AEA0E941F0185E50E942C
+:1018E0005A0180E80E941F018AEA0E941F0185E5D3
+:1018F0000E945A0180E30E94890020E030E090E8D5
+:1019000011C0283BEBE03E07B1F18091620082609C
+:1019100080936200CFECD7E02197F1F700C0000080
+:101920002F5F3F4F809162008E7F80936200809195
+:10193000620082608093620072BA11BA8091620084
+:101940008068809362001BBA95BB809162008061C1
+:101950008093620080916200816080936200809138
+:1019600062008D7F80936200D2E0DA95F1F700C0CB
+:1019700080B38F3F31F61BBA15BA80916200806147
+:101980008093620080916200816080936200809108
+:101990006200826080936200C798283B3B4009F454
+:1019A00029C860E070E08AE00E94AC0223C8C091C0
+:1019B0000D0180910E01D0E0D82B00910F01809194
+:1019C000100110E0182BC69AC49AC39ABC9ABB9A0D
+:1019D000B80188E00E94AC0201151105E9F42DC0A0
+:1019E00080618093620080916200816080936200D8
+:1019F000809162008D7F80936200C39AC49832E028
+:101A00003A95F1F700C080B30E94A103015011097B
+:101A100021960115110589F072BA11BA8091620000
+:101A2000806880936200CBBBD5BB80916200D5FFFC
+:101A3000D7CF8F7E80936200D6CF1BBA15BA809124
+:101A40006200806180936200809162008260809376
+:101A50006200C49AC39ABC98C498C6980C94FA04BD
+:101A60000E941A020C94FA04E0900D0180910E017C
+:101A7000F12CF82A00910F018091100110E0182B31
+:101A8000C79AC49AC39ABC9ABB9A8091620082603A
+:101A9000809362000115110509F4D1C0D1E1AD2E8A
+:101AA000D1E0BD2E9701207E6501F501E701612C93
+:101AB00006C0CE01807E2817390709F06FC08191DA
+:101AC0008F3F09F063942196015011095F0189F756
+:101AD000662009F4B4C08AEA0E94F0000E945A000D
+:101AE00085E20E94C3006A94862D0E94C300F6011D
+:101AF00081916F018F3F09F449C0C49AC39A9091B4
+:101B0000620092609093620090916200906890935E
+:101B10006200EBBAF5BA27014424F0E25F2290910B
+:101B20006200F5FC37C090619093620071BA82BB8D
+:101B300080916200816080936200809162008D7F5D
+:101B40008093620022E02A95F1F700C0C39832E04A
+:101B50003A95F1F700C0C39A1BBA15BA809162009A
+:101B60008061809362008091620082608093620055
+:101B700072BA11BAC70101966620A1F07C016A947D
+:101B8000F60181916F018F3F09F0B7CFFFEFEF1A98
+:101B9000FF0AADCF9F7E90936200C8CF61109BCFAC
+:101BA0007E0180CF89E20E94C3004AE14A95F1F7A5
+:101BB00000C06894F7F82E2D9F2D40EA56E861E0AA
+:101BC00070E030E0F6013197452861F052C03AE10B
+:101BD0003A95F1F700C041505109610971093A2F56
+:101BE00009F4B9C272BA11BA809162008068809318
+:101BF00062002BBB95BB8091620080618093620084
+:101C000080916200816080936200809162008D7F8C
+:101C100080936200C39AC49882E08A95F1F700C06D
+:101C2000A0B380916200826080936200A313CFCF43
+:101C300080818313CCCF0115110509F0B1CF8091BC
+:101C40006200826080936200BC98C498C79860E08C
+:101C500070E08AE00E94AC020C94FA043AE13A95F2
+:101C6000F1F700C041505109610971093A2F09F497
+:101C700072C272BA11BA8091620080688093620069
+:101C80002BBB95BB809162008F7E80936200809118
+:101C90006200816080936200809162008D7F8093FA
+:101CA0006200C39AC49882E08A95F1F700C0A0B39D
+:101CB00080916200826080936200A313CFCF808105
+:101CC0008313CCCFB8CFC0910D0180910E01D0E02D
+:101CD000D82B00910F018091100110E0182BC69AAB
+:101CE000B8018CE00E94AC020115110509F5DCCDAC
+:101CF000806180936200809162008F7D809362009A
+:101D000062E06A95F1F700C080B390916200906242
+:101D100090936200909162009160909362000E94A3
+:101D2000A1030150110921960115110509F4BCCD3B
+:101D3000809162008E7F8093620080916200826059
+:101D40008093620072BA11BACBBBD5BB809162009E
+:101D5000D5FFCECF8F7E80936200CDCF00910D0155
+:101D600080910E0110E0182BE0900F01809110017E
+:101D7000F12CF82AC79AE114F10409F4DBC981E1D6
+:101D8000C82E81E0D82EF601B1906F0180EF0E943D
+:101D900089008AEA0E945A0165E58AEA92E80E946F
+:101DA000950180EA0E945A016B2DE801D068CE01AE
+:101DB0000E949501F5E8FA95F1F70000AE0180E088
+:101DC00090E030E015FF0BC05BC035E83A95F1F7C5
+:101DD00000000196362F883C910509F482C02091BD
+:101DE00062002E7F20936200209162002260209387
+:101DF000620072BA11BA20916200206820936200DA
+:101E00004BBB55BB20916200206120936200209162
+:101E10006200216020936200209162002D7F209358
+:101E2000620022E02A95F1F700C060B320916200C1
+:101E30002260209362006313C8CFB312C6CF2091F3
+:101E400062002260209362001BBA15BA20916200E2
+:101E50002061209362000A970CF0D0C80F5F1F4FDB
+:101E6000D1E0ED1AF10809F08ECFC79864C9C5E832
+:101E7000CA95F1F700000196362F883C910589F14B
+:101E8000209162002E7F20936200209162002260E8
+:101E90002093620072BA11BA2091620020682093E8
+:101EA00062004BBB55BB209162002F7E20936200E5
+:101EB00020916200216020936200209162002D7FBA
+:101EC0002093620062E06A95F1F700C060B3209150
+:101ED00062002260209362003613C9CF6B11C7CF16
+:101EE000AECF809162008260809362001BBA15BA07
+:101EF00080916200806180936200C7980C94FA041C
+:101F000080910D0120910E0190E0922B40910F01E4
+:101F10002091100150E0522BC79A4115510509F448
+:101F200082CBE1E1F1E024C02061209362002091A6
+:101F300062002B7F2093620022E02A95F1F700C017
+:101F40002091620024602093620072BA11BA1BBA19
+:101F500015BA2091620020612093620020916200F6
+:101F600021602093620001964150510909F45BCB36
+:101F70003191209162002E7F2093620020916200B7
+:101F800022602093620071BA32BB8BBB95BB20915B
+:101F9000620095FFC9CF2F7E20936200C8CF2091A9
+:101FA0000D0180910E0130E0382B40910F0180919E
+:101FB000100150E0582BC69A4115510509F4DCC0B8
+:101FC00080E090E026C09695879580FD56C0969556
+:101FD000879580FD5AC09695879580FD5EC0969541
+:101FE000879580FD62C09695879580FD66C0969521
+:101FF000879580FD6AC09695879580FD6EC0969501
+:102000008795415051092F5F3F4F4115510509F404
+:1020100072C0609162006E7F6093620060916200A6
+:1020200062606093620072BA11BA2BBB35BB6091DB
+:10203000620035FD81C06061609362006091620062
+:102040006F7D60936200C2E0CA95F1F700C070B383
+:102050006091620060626093620060916200616002
+:1020600060936200872780FFAECF96958795D1E079
+:102070008D27D0EA9D2780FFAACF96958795E1E02E
+:102080008E27E0EA9E2780FFA6CF96958795F1E000
+:102090008F27F0EA9F2780FFA2CF9695879561E072
+:1020A000862760EA962780FF9ECF96958795C1E0A8
+:1020B0008C27C0EA9C2780FF9ACF96958795D1E020
+:1020C0008D27D0EA9D2780FF96CF96958795E1E0F2
+:1020D0008E27E0EA9E2780FF92CF96958795F1E0C4
+:1020E0008F27F0EA9F27415051092F5F3F4F41153D
+:1020F000510509F08ECFD82FC92F1BBA15BA809180
+:1021000062008061809362008091620081608093B0
+:1021100062008091620082608093620062E070E001
+:102120008CE00E94AC028D2F0E94A1038C2F0E9494
+:10213000A103C6980C94FA046F7E609362007ECF70
+:102140008D7F8093620088CB8F7E80936200BBCAB4
+:1021500050580C94B10680916200826080936200B6
+:10216000BC98C498C7980C94FA04C0E0D0E03BCB6C
+:102170008D7F80936200B3CAC0E0D0E0BECFF894F8
+:02218000FFCF8F
:00000001FF