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:
authorAlexey 'Cluster' Avdyukhin <clusterrr@clusterrr.com>2020-12-01 19:43:26 +0300
committerAlexey 'Cluster' Avdyukhin <clusterrr@clusterrr.com>2020-12-01 19:48:13 +0300
commit43d5d6c64243331a2fb5a36532c941716e50556c (patch)
tree8b43737e7cdd97b75f7abf026717bf2567950aba
parent4e4ca3f1f4d976f90084e128209000bd87d036a0 (diff)
FDS dumping/writing
-rw-r--r--dumper.c450
-rw-r--r--dumper.h45
-rw-r--r--famicom-dumper.hex859
3 files changed, 947 insertions, 407 deletions
diff --git a/dumper.c b/dumper.c
index 386494c..f024bf6 100644
--- a/dumper.c
+++ b/dumper.c
@@ -32,23 +32,6 @@
#include "dumper.h"
#include "crc.h"
-#define LED_RED_ON PORTB |= (1<<7)
-#define LED_RED_OFF PORTB &= ~(1<<7)
-#define LED_GREEN_ON PORTB |= (1<<6)
-#define LED_GREEN_OFF PORTB &= ~(1<<6)
-#define ROMSEL_HI PORTF |= (1<<1)
-#define ROMSEL_LOW PORTF &= ~(1<<1)
-#define PHI2_HI PORTF |= (1<<0)
-#define PHI2_LOW PORTF &= ~(1<<0)
-#define MODE_READ { PORTD = 0xFF; DDRD = 0; }
-#define MODE_WRITE DDRD = 0xFF
-#define PRG_READ PORTF |= (1<<7)
-#define PRG_WRITE PORTF &= ~(1<<7)
-#define CHR_READ_HI PORTF |= (1<<5)
-#define CHR_READ_LOW PORTF &= ~(1<<5)
-#define CHR_WRITE_HI PORTF |= (1<<2)
-#define CHR_WRITE_LOW PORTF &= ~(1<<2)
-
static void (*jump_to_bootloader)(void) = (void*)0xF800;
ISR(USART0_RX_vect)
@@ -428,213 +411,306 @@ static void write_flash(uint16_t address, uint16_t len, uint8_t* data)
LED_RED_OFF;
}
-static void read_fds_send(uint8_t start_block, uint8_t block_count)
+static inline void delay_clock(t)
{
- uint8_t status;
- uint8_t end_of_head = 0;
- uint8_t current_block = 0;
- uint16_t b;
+ if (t < 30000)
+ _delay_us(t * 1000000 / 1789773);
+ else
+ _delay_ms(t * 1000 / 1789773);
+}
- write_prg_byte(0x4022, 0x00); // disable IRQ
- write_prg_byte(0x4023, 0x00); // disable registers
- write_prg_byte(0x4023, 0x01); // enable disk registers
- write_prg_byte(0x4025, 0x2E); // reset
- // waiting for disk
- while (1)
+static uint8_t transfer_fds_byte(uint8_t *output, uint8_t input, uint8_t *end_of_head)
+{
+ TCNT1 = 0;
+ while (!IRQ_FIRED)
{
- status = read_prg_byte(0x4032);
- if (!(status & 1)) break; // disk inserted
+ // waiting for interrupt
+ // timeout 5 secs
+ if (TCNT1 >= 39060)
+ {
+ write_prg_byte(FDS_CONTROL, FDS_CONTROL_READ | FDS_CONTROL_RESET); // reset, stop
+ comm_start(COMMAND_FDS_TIMEOUT, 0);
+ return 0;
+ }
}
- write_prg_byte(0x4025, 0x2E); // reset
- _delay_ms(800); // 916522 cycles
- write_prg_byte(0x4025, 0x2F); // start motor
- write_prg_byte(0x4025, 0x2D); // unreset
-
- _delay_ms(250); // 268531 cycles
- write_prg_byte(0x4025, 0x2E); // reset
- write_prg_byte(0x4025, 0x2F); // start motor
- write_prg_byte(0x4025, 0x2D); // unreset
-
- // waiting until drive is rewinded
- while (1)
+ if (output)
+ *output = read_prg_byte(FDS_DATA_READ);
+ write_prg_byte(FDS_DATA_WRITE, input); // clear interrupt
+ uint8_t status = read_prg_byte(FDS_DISK_STATUS);
+ if (end_of_head)
+ *end_of_head |= (status >> 6) & 1;
+ TCNT1 = 0;
+ while (IRQ_FIRED)
{
- status = read_prg_byte(0x4032);
- if (!(status & 2)) break; // ready
+ // is interrupt flag cleared?
+ // timeout 5 secs
+ if (TCNT1 >= 39060)
+ {
+ write_prg_byte(FDS_CONTROL, FDS_CONTROL_READ | FDS_CONTROL_RESET); // reset, stop
+ comm_start(COMMAND_FDS_TIMEOUT, 0);
+ return 0;
+ }
}
+ return 1;
+}
- _delay_ms(FDS_PAUSE_BEFORE_FIRST_BLOCK); // 486974 cycles
+static uint8_t read_fds_block_send(uint16_t length, uint8_t send, uint8_t *crc_ok, uint8_t *end_of_head, uint16_t *file_size, uint32_t gap_delay)
+{
+ uint8_t data;
+ uint8_t status;
+ uint32_t b;
- LED_GREEN_ON;
- if (start_block == 0)
- comm_start(COMMAND_FDS_READ_RESULT_BLOCK, 58);
- write_prg_byte(0x4025, 0x6D); // start transfer
- write_prg_byte(0x4025, 0xED); // enable IRQ
- for (b = 0; b < 56; b++)
+ write_prg_byte(FDS_CONTROL, FDS_CONTROL_READ | FDS_CONTROL_MOTOR_ON); // motor on without transfer
+ delay_clock(gap_delay);
+ if (send)
{
- while (!IRQ_FIRED); // waiting for interrupt
- uint8_t data = read_prg_byte(0x4031);
- //write_prg_byte(0x4024, 0xFF); // clear interrupt
- // status read also clears interrupt
- status = read_prg_byte(0x4030);
- end_of_head |= (status >> 6) & 1;
- if (start_block == 0)
+ LED_GREEN_ON;
+ comm_start(COMMAND_FDS_READ_RESULT_BLOCK, length + 2);
+ }
+ // start transfer, enable IRQ
+ write_prg_byte(FDS_CONTROL, FDS_CONTROL_READ | FDS_CONTROL_MOTOR_ON | FDS_CONTROL_TRANSFER_ON | FDS_CONTROL_IRQ_ON);
+ for (b = 0; b < length; b++)
+ {
+ if (!transfer_fds_byte(&data, 0, end_of_head))
+ return 0;
+ if (file_size)
+ {
+ if (b == 13)
+ *file_size |= data;
+ else if (b == 14)
+ *file_size |= data << 8;
+ }
+ if (send)
comm_send_byte(data);
- while (IRQ_FIRED); // is interrupt flag cleared?
}
- write_prg_byte(0x4025, 0xED); // enable CRC control
- while (!IRQ_FIRED); // waiting for interrupt
- read_prg_byte(0x4031);
- write_prg_byte(0x4024, 0xFF); // clear interrupt
- while (IRQ_FIRED); // is interrupt flag cleared?
- status = read_prg_byte(0x4030);
- end_of_head |= (status >> 6) & 1;
- if (start_block == 0)
+ if (!transfer_fds_byte(0, 0, end_of_head))
+ return 0;
+ write_prg_byte(FDS_CONTROL, FDS_CONTROL_READ | FDS_CONTROL_MOTOR_ON | FDS_CONTROL_TRANSFER_ON | FDS_CONTROL_IRQ_ON | FDS_CONTROL_CRC); // enable CRC control
+ if (!transfer_fds_byte(0, 0, end_of_head))
+ return 0;
+ status = read_prg_byte(FDS_DISK_STATUS);
+ *crc_ok &= ((status >> 4) & 1) ^ 1;
+ *end_of_head |= (status >> 6) & 1;
+ if (send)
{
- comm_send_byte(((status >> 4) & 1) ^ 1); // CRC check result
- comm_send_byte(end_of_head); // end of head meet?
+ comm_send_byte(*crc_ok); // CRC check result
+ comm_send_byte(*end_of_head); // end of head meet?
}
- current_block++;
-
- // reading file amount block
- if (!end_of_head && ((start_block + block_count > current_block) || (block_count = 0)))
+ LED_GREEN_OFF;
+ return 1; // success
+}
+
+static uint8_t write_fds_block(uint8_t *data, uint16_t length, uint32_t gap_delay)
+{
+ uint8_t end_of_head = 0;
+ LED_RED_ON;
+ write_prg_byte(FDS_CONTROL, FDS_CONTROL_READ | FDS_CONTROL_MOTOR_ON); // motor on without transfer
+ read_prg_byte(FDS_DRIVE_STATUS); // check if disk is inserted
+ write_prg_byte(FDS_CONTROL, FDS_CONTROL_WRITE | FDS_CONTROL_MOTOR_ON); // enable writing without transfer
+ delay_clock(gap_delay);
+ write_prg_byte(FDS_DATA_WRITE, 0x00); // write $00
+ // start transfer, enable IRQ
+ write_prg_byte(FDS_CONTROL, FDS_CONTROL_WRITE | FDS_CONTROL_MOTOR_ON | FDS_CONTROL_TRANSFER_ON | FDS_CONTROL_IRQ_ON);
+ transfer_fds_byte(0, 0x80, &end_of_head); // write $80
+ while (length)
{
- write_prg_byte(0x4025, 0x2D); // motor on without transfer
- // waiting until drive is ready
- while (1)
+ if (end_of_head)
{
- status = read_prg_byte(0x4032);
- if (!(status & 2)) break; // ready
+ write_prg_byte(FDS_CONTROL, FDS_CONTROL_READ | FDS_CONTROL_RESET); // reset, stop
+ comm_start(COMMAND_FDS_END_OF_HEAD, 0);
+ return 0;
}
- _delay_ms(FDS_PAUSE_BETWEEN_BLOCKS); // 9026 cycles
- if ((current_block >= start_block) && ((current_block < start_block + block_count) || (block_count == 0)))
- comm_start(COMMAND_FDS_READ_RESULT_BLOCK, 4);
- write_prg_byte(0x4025, 0x6D); // start transfer
- write_prg_byte(0x4025, 0xED); // enable IRQ
- for (b = 0; b < 2; b++)
+ if (!transfer_fds_byte(0, *data, &end_of_head))
{
- while (!IRQ_FIRED); // waiting for interrupt
- uint8_t data = read_prg_byte(0x4031);
- //write_prg_byte(0x4024, 0xFF); // clear interrupt
- // status read also clears interrupt
- status = read_prg_byte(0x4030);
- end_of_head |= (status >> 6) & 1;
- if ((current_block >= start_block) && ((current_block < start_block + block_count) || (block_count == 0)))
- comm_send_byte(data);
- while (IRQ_FIRED); // is interrupt flag cleared?
+ write_prg_byte(FDS_CONTROL, FDS_CONTROL_READ | FDS_CONTROL_RESET); // reset, stop
+ comm_start(COMMAND_FDS_TIMEOUT, 0);
+ return 0;
}
- write_prg_byte(0x4025, 0xED); // enable CRC control
- while (!IRQ_FIRED); // waiting for interrupt
- read_prg_byte(0x4031);
- write_prg_byte(0x4024, 0xFF); // clear interrupt
- while (IRQ_FIRED); // is interrupt flag cleared?
- status = read_prg_byte(0x4030);
- end_of_head |= (status >> 6) & 1;
- if ((current_block >= start_block) && ((current_block < start_block + block_count) || (block_count == 0)))
+ data++;
+ length--;
+ }
+ if (!transfer_fds_byte(0, 0xFF, &end_of_head))
+ {
+ write_prg_byte(FDS_CONTROL, FDS_CONTROL_READ | FDS_CONTROL_RESET); // reset, stop
+ comm_start(COMMAND_FDS_TIMEOUT, 0);
+ return 0;
+ }
+ if (end_of_head)
+ {
+ write_prg_byte(FDS_CONTROL, FDS_CONTROL_READ | FDS_CONTROL_RESET); // reset, stop
+ comm_start(COMMAND_FDS_END_OF_HEAD, 0);
+ return 0;
+ }
+ write_prg_byte(FDS_CONTROL, FDS_CONTROL_WRITE | FDS_CONTROL_MOTOR_ON | FDS_CONTROL_TRANSFER_ON | FDS_CONTROL_IRQ_ON | FDS_CONTROL_CRC); // enable CRC control
+ delay_clock(FDS_WRITE_CRC_DELAY);
+ TCNT1 = 0;
+ while (1)
+ {
+ uint8_t status = read_prg_byte(FDS_DRIVE_STATUS);
+ if (!(status & 2))
+ break; // ready
+ // timeout 1 sec
+ if (TCNT1 >= 7812)
{
- comm_send_byte(((status >> 4) & 1) ^ 1); // CRC check result
- comm_send_byte(end_of_head); // end of head meet?
+ write_prg_byte(FDS_CONTROL, FDS_CONTROL_READ | FDS_CONTROL_RESET); // reset, stop
+ comm_start(COMMAND_FDS_TIMEOUT, 0);
+ return 0;
}
- current_block++;
+ }
+ LED_RED_OFF;
+ return 1;
+}
+
+static void fds_transfer(uint8_t block_read_start, uint8_t block_read_count, uint8_t block_write_count, uint8_t *block_write_ids, uint16_t *write_lengths,
+ uint8_t *write_data)
+{
+ uint8_t crc_ok = 1;
+ uint8_t end_of_head = 0;
+ uint8_t current_block = 0;
+ uint8_t current_writing_block = 0;
+
+ write_prg_byte(FDS_IRQ_CONTROL, 0x00); // disable timer IRQ
+ write_prg_byte(FDS_MASTER_IO, 0x01); // enable disk registers
+ write_prg_byte(FDS_CONTROL, FDS_CONTROL_READ | FDS_CONTROL_RESET); // reset
+ uint8_t ram_adapter_connected = 1;
+ write_prg_byte(FDS_EXT_WRITE, 0x00); // Ext. connector
+ write_prg_byte(0x0000, 0xFF); // To prevent open bus read
+ if ((read_prg_byte(FDS_EXT_READ) & 0x7F) != 0x00)
+ ram_adapter_connected = 0;
+ write_prg_byte(FDS_EXT_WRITE, 0xFF); // Ext. connector
+ write_prg_byte(0x0000, 0x00); // To prevent open bus read
+ if ((read_prg_byte(FDS_EXT_READ) & 0x7F) != 0x7F)
+ ram_adapter_connected = 0;
+ if (!ram_adapter_connected)
+ {
+ comm_start(COMMAND_FDS_NOT_CONNECTED, 0);
+ return;
}
+ if (read_prg_byte(FDS_DRIVE_STATUS) & 1)
+ {
+ comm_start(COMMAND_FDS_DISK_NOT_INSERTED, 0);
+ return;
+ }
+ delay_clock(916500); // ~916500 cycles
+ write_prg_byte(FDS_CONTROL, FDS_CONTROL_READ | FDS_CONTROL_MOTOR_ON); // monor on, unreset
+ delay_clock(268500); // ~268500 cycles
+ write_prg_byte(FDS_CONTROL, FDS_CONTROL_READ | FDS_CONTROL_RESET); // reset
+ write_prg_byte(FDS_CONTROL, FDS_CONTROL_READ | FDS_CONTROL_MOTOR_ON); // monor on, unreset
+ // waiting until drive is rewinded
+ TCNT1 = 0;
+ uint8_t secs = 0;
+ do
+ {
+ // timeout 15 secs
+ if (TCNT1 >= 7812)
+ {
+ TCNT1 = 0;
+ secs++;
+ if (secs >= 15)
+ {
+ write_prg_byte(FDS_CONTROL, FDS_CONTROL_READ | FDS_CONTROL_RESET); // reset, stop
+ comm_start(COMMAND_FDS_TIMEOUT, 0);
+ return;
+ }
+ }
+ } while (read_prg_byte(FDS_DRIVE_STATUS) & 2);
- while (!end_of_head && ((start_block + block_count > current_block) || (block_count = 0)))
+ // disk info block
+ if (block_write_count && (current_block == block_write_ids[current_writing_block]))
{
- // reading file header block
- uint16_t file_size = 0; // size of the next file
+ // gap delay while writing = ~28300 bits = (~28300 / 8)bits * ~165cycles = ~583687.5
+ uint16_t write_length = write_lengths[current_writing_block];
+ if (!write_fds_block(write_data, write_length, FDS_WRITE_GAP_BEFORE_FIRST_BLOCK))
+ return;
+ write_data += write_length;
+ current_writing_block++;
+ block_write_count--;
+ } else
+ {
+ // gap delay while reading = ~486974 cycles
+ if (!read_fds_block_send(56, (current_block >= block_read_start) && block_read_count, &crc_ok, &end_of_head, 0, FDS_READ_GAP_BEFORE_FIRST_BLOCK))
+ return;
+ }
+ if (block_read_count)
+ block_read_count--;
+ current_block++;
- write_prg_byte(0x4025, 0x2D); // motor on without transfer
- // waiting until drive is ready
- while (1)
+ if (crc_ok && !end_of_head && (block_read_count || block_write_count))
+ {
+ // file amount block
+ if (block_write_count && (current_block == block_write_ids[current_writing_block]))
{
- status = read_prg_byte(0x4032);
- if (!(status & 2)) break; // ready
- }
- _delay_ms(FDS_PAUSE_BETWEEN_BLOCKS); // 9026 cycles
- if ((current_block >= start_block) && ((current_block < start_block + block_count) || (block_count == 0)))
- comm_start(COMMAND_FDS_READ_RESULT_BLOCK, 18);
- write_prg_byte(0x4025, 0x6D); // start transfer
- write_prg_byte(0x4025, 0xED); // enable IRQ
- for (b = 0; b < 16; b++)
+ uint16_t write_length = write_lengths[current_writing_block];
+ if (!write_fds_block(write_data, write_length, FDS_WRITE_GAP_BETWEEN_BLOCKS))
+ return;
+ write_data += write_length;
+ current_writing_block++;
+ block_write_count--;
+ } else
{
- while (!IRQ_FIRED); // waiting for interrupt
- uint8_t data = read_prg_byte(0x4031);
- //write_prg_byte(0x4024, 0xFF); // clear interrupt
- // status read also clears interrupt
- status = read_prg_byte(0x4030);
- end_of_head |= (status >> 6) & 1;
- if ((current_block >= start_block) && ((current_block < start_block + block_count) || (block_count == 0)))
- comm_send_byte(data);
- if (b == 13)
- file_size |= data;
- else if (b == 14)
- file_size |= data << 8;
- while (IRQ_FIRED); // is interrupt flag cleared?
+ if (!read_fds_block_send(2, (current_block >= block_read_start) && block_read_count, &crc_ok, &end_of_head, 0, FDS_READ_GAP_BETWEEN_BLOCKS))
+ return;
}
- write_prg_byte(0x4025, 0xED); // enable CRC control
- while (!IRQ_FIRED); // waiting for interrupt
- read_prg_byte(0x4031);
- write_prg_byte(0x4024, 0xFF); // clear interrupt
- while (IRQ_FIRED); // is interrupt flag cleared?
- status = read_prg_byte(0x4030);
- end_of_head |= (status >> 6) & 1;
- if ((current_block >= start_block) && ((current_block < start_block + block_count) || (block_count == 0)))
+ if (block_read_count)
+ block_read_count--;
+ current_block++;
+ }
+
+ while (crc_ok && !end_of_head && (block_read_count || block_write_count))
+ {
+ // file header block
+ uint16_t file_size = 0; // size of the next file
+ if (block_write_count && (current_block == block_write_ids[current_writing_block]))
+ {
+ uint16_t write_length = write_lengths[current_writing_block];
+ if (!write_fds_block(write_data, write_length, FDS_WRITE_GAP_BETWEEN_BLOCKS))
+ return;
+ write_data += write_length;
+ current_writing_block++;
+ block_write_count--;
+ } else
{
- comm_send_byte(((status >> 4) & 1) ^ 1); // CRC check result
- comm_send_byte(end_of_head); // end of head meet?
+ if (!read_fds_block_send(16, (current_block >= block_read_start) && block_read_count, &crc_ok, &end_of_head, &file_size, FDS_READ_GAP_BETWEEN_BLOCKS))
+ return;
}
- current_block++;
+ if (block_read_count)
+ block_read_count--;
+ current_block++;
- // reading file data
- if (!end_of_head && ((start_block + block_count > current_block) || (block_count = 0)))
+ if (crc_ok && !end_of_head && (block_read_count || block_write_count))
{
- write_prg_byte(0x4025, 0x2D); // motor on without transfer
- // waiting until drive is ready
- while (1)
+ // file data block
+ if (block_write_count && (current_block == block_write_ids[current_writing_block]))
{
- status = read_prg_byte(0x4032);
- if (!(status & 2)) break; // ready
- }
- _delay_ms(FDS_PAUSE_BETWEEN_BLOCKS); // 9026 cycles
- if ((current_block >= start_block) && ((current_block < start_block + block_count) || (block_count == 0)))
- comm_start(COMMAND_FDS_READ_RESULT_BLOCK, file_size + 3);
- write_prg_byte(0x4025, 0x6D); // start transfer
- write_prg_byte(0x4025, 0xED); // enable IRQ
- for (b = 0; b < file_size + 1; b++)
- {
- while (!IRQ_FIRED); // waiting for interrupt
- uint8_t data = read_prg_byte(0x4031);
- //write_prg_byte(0x4024, 0xFF); // clear interrupt
- // status read also clears interrupt
- status = read_prg_byte(0x4030);
- end_of_head |= (status >> 6) & 1;
- if ((current_block >= start_block) && ((current_block < start_block + block_count) || (block_count == 0)))
- comm_send_byte(data);
- while (IRQ_FIRED); // is interrupt flag cleared?
- }
- write_prg_byte(0x4025, 0xED); // enable CRC control
- while (!IRQ_FIRED); // waiting for interrupt
- read_prg_byte(0x4031);
- write_prg_byte(0x4024, 0xFF); // clear interrupt
- while (IRQ_FIRED); // is interrupt flag cleared?
- status = read_prg_byte(0x4030);
- end_of_head |= (status >> 6) & 1;
- if ((current_block >= start_block) && ((current_block < start_block + block_count) || (block_count == 0)))
+ uint16_t write_length = write_lengths[current_writing_block];
+ if (!write_fds_block(write_data, write_length, FDS_WRITE_GAP_BETWEEN_BLOCKS))
+ return;
+ write_data += write_length;
+ current_writing_block++;
+ block_write_count--;
+ } else
{
- comm_send_byte(((status >> 4) & 1) ^ 1); // CRC check result
- comm_send_byte(end_of_head); // end of head meet?
+ if (!read_fds_block_send(file_size + 1, (current_block >= block_read_start) && block_read_count, &crc_ok, &end_of_head, 0, FDS_READ_GAP_BETWEEN_BLOCKS))
+ return;
}
+ if (block_read_count)
+ block_read_count--;
current_block++;
}
}
- write_prg_byte(0x4025, 0x26); // reset, stop
+ write_prg_byte(FDS_CONTROL, FDS_CONTROL_READ | FDS_CONTROL_RESET); // reset, stop
_delay_ms(50);
+ if (current_writing_block && !block_write_count && !block_read_count)
+ {
+ comm_start(COMMAND_FDS_WRITE_DONE, 0);
+ return;
+ }
comm_start(COMMAND_FDS_READ_RESULT_END, 0);
- LED_GREEN_OFF;
}
-void get_mirroring()
+static void get_mirroring()
{
comm_start(COMMAND_MIRRORING_RESULT, 4);
LED_GREEN_ON;
@@ -806,6 +882,15 @@ int main (void)
comm_start(COMMAND_CHR_WRITE_DONE, 0);
break;
+ case COMMAND_FDS_READ_REQUEST:
+ fds_transfer(recv_buffer[0], recv_buffer[1], 0, 0, 0, 0);
+ break;
+
+ case COMMAND_FDS_WRITE_REQUEST:
+ fds_transfer(0, 0, recv_buffer[0], (uint8_t*) &recv_buffer[1], (uint16_t*) &recv_buffer[1 + recv_buffer[0]],
+ (uint8_t*) &recv_buffer[1 + recv_buffer[0] + recv_buffer[0] * 2]);
+ break;
+
case COMMAND_MIRRORING_REQUEST:
get_mirroring();
break;
@@ -815,6 +900,9 @@ int main (void)
MCUCSR = 0;
jump_to_bootloader();
}
+
+ LED_GREEN_OFF;
+ LED_RED_OFF;
}
}
}
diff --git a/dumper.h b/dumper.h
index 994eb87..0beb761 100644
--- a/dumper.h
+++ b/dumper.h
@@ -11,7 +11,48 @@
#define IRQ_FIRED (!(PINF & (1<<6)))
-#define FDS_PAUSE_BEFORE_FIRST_BLOCK 300
-#define FDS_PAUSE_BETWEEN_BLOCKS 5
+#define FDS_IRQ_CONTROL 0x4022
+#define FDS_MASTER_IO 0x4023
+#define FDS_DATA_WRITE 0x4024
+#define FDS_CONTROL 0x4025
+#define FDS_EXT_WRITE 0x4026
+#define FDS_DISK_STATUS 0x4030
+#define FDS_DATA_READ 0x4031
+#define FDS_DRIVE_STATUS 0x4032
+#define FDS_EXT_READ 0x4033
+
+#define FDS_CONTROL_MOTOR_ON 0b00000001
+#define FDS_CONTROL_RESET 0b00000010
+#define FDS_CONTROL_READ 0b00100100
+#define FDS_CONTROL_WRITE 0b00100000
+#define FDS_CONTROL_CRC 0b00010000
+#define FDS_CONTROL_TRANSFER_ON 0b01000000
+#define FDS_CONTROL_IRQ_ON 0b10000000
+
+#define FDS_READ_GAP_BEFORE_FIRST_BLOCK 486974
+#define FDS_WRITE_GAP_BEFORE_FIRST_BLOCK 580000
+#define FDS_READ_GAP_BETWEEN_BLOCKS 9026
+#define FDS_WRITE_GAP_BETWEEN_BLOCKS 17917
+#define FDS_WRITE_CRC_DELAY 897
+
+#define LED_RED_ON PORTB |= (1<<7)
+#define LED_RED_OFF PORTB &= ~(1<<7)
+#define LED_GREEN_ON PORTB |= (1<<6)
+#define LED_GREEN_OFF PORTB &= ~(1<<6)
+
+#define ROMSEL_HI PORTF |= (1<<1)
+#define ROMSEL_LOW PORTF &= ~(1<<1)
+#define PHI2_HI PORTF |= (1<<0)
+#define PHI2_LOW PORTF &= ~(1<<0)
+#define MODE_READ { PORTD = 0xFF; DDRD = 0; }
+#define MODE_WRITE DDRD = 0xFF
+#define PRG_READ PORTF |= (1<<7)
+#define PRG_WRITE PORTF &= ~(1<<7)
+#define CHR_READ_HI PORTF |= (1<<5)
+#define CHR_READ_LOW PORTF &= ~(1<<5)
+#define CHR_WRITE_HI PORTF |= (1<<2)
+#define CHR_WRITE_LOW PORTF &= ~(1<<2)
+
+#define DELAY_CLOCK(t) {if (t < 30000) _delay_us(t * 1000000 / 1789773); else _delay_ms(t * 1000 / 1789773);}
#endif
diff --git a/famicom-dumper.hex b/famicom-dumper.hex
index 2967035..5bf3e2a 100644
--- a/famicom-dumper.hex
+++ b/famicom-dumper.hex
@@ -1,12 +1,12 @@
-:100000000C94C6010C94D8010C94D8010C94D8011E
-:100010000C94D8010C94D8010C94D8010C94D801FC
-:100020000C94D8010C94D8010C94D8010C94D801EC
-:100030000C94D8010C94D8010C94D8010C94D801DC
-:100040000C94D8010C94D8010C94DF020C94D801C4
-:100050000C94D8010C94D8010C94D8010C94D801BC
-:100060000C94D8010C94D8010C94D8010C94D801AC
-:100070000C94D8010C94D8010C94D8010C94D8019C
-:100080000C94D8010C94D8010C94D801005EBCE209
+:100000000C94C6010C94E3010C94E3010C94E301FD
+:100010000C94E3010C94E3010C94E3010C94E301D0
+:100020000C94E3010C94E3010C94E3010C94E301C0
+:100030000C94E3010C94E3010C94E3010C94E301B0
+:100040000C94E3010C94E3010C94F3020C94E3018F
+:100050000C94E3010C94E3010C94E3010C94E30190
+:100060000C94E3010C94E3010C94E3010C94E30180
+:100070000C94E3010C94E3010C94E3010C94E30170
+:100080000C94E3010C94E3010C94E301005EBCE2E8
:10009000613FDD83C29C7E20A3FD1F419DC3217F64
:1000A000FCA2401E5F01E3BD3E6082DC237D9FC158
:1000B000421CFEA0E1BF5D0380DE3C62BEE0025C4C
@@ -55,219 +55,630 @@
:10036000818F404F018DC04D804C418C0044C18431
:10037000818540450187C047804641860182C04251
:10038000804341830041C1818180404011241FBED0
-:10039000CFEFD0E1DEBFCDBF19E0A0E0B1E001C0FA
-:1003A0001D92AD30B107E1F70E9408030C947E085E
-:1003B0000C9400008BBB95BB95FD06C0809162003C
-:1003C0008061809362000895809162008F7E8093A7
-:1003D000620008950F931F938C01809162008E7FBD
-:1003E00080936200809162008260809362008FEF50
-:1003F00082BB11BA80916200806880936200C8015C
-:100400000E94DA018091620081608093620017FD92
-:1004100015C080916200826080936200C39AC49A82
-:1004200082E08A95F1F780B3909162009260909398
-:100430006200C39AC49A1F910F910895809162003F
-:100440008D7F80936200C39AC498EACF0F931F9365
-:1004500002E610E0F80120812E7F208320812260B7
-:1004600020832FEF22BB11BA0E94DA01F8018081AC
-:100470008F7D808382E08A95F1F780B390819062CE
-:1004800090839081916090831F910F9108950F93B5
-:100490001F938C01809162008E7F80936200809117
-:1004A00062008260809362008FEF81BB8091620066
-:1004B0008F778093620062BBC8010E94DA0182E0FC
-:1004C0008A95F1F78091620081608093620017FD48
-:1004D0002DC080916200826080936200C39AC49AAA
-:1004E00092E0892F8A95F1F7809162008E7F809348
-:1004F000620080916200826080936200C39AC49A15
-:100500009A95F1F7809162008068809362008FEF86
-:1005100082BB11BA80E090E00E94DA018091620013
-:100520008160809362001F910F9108958091620015
-:100530008D7F80936200C398C49AD2CF1F9382E1CB
-:1005400064E070E00E949807C69A80E090E00E9404
-:10055000DA0112E0812F8A95F1F781B186958695AF
-:1005600081700E94800780E094E00E94DA01812F70
-:100570008A95F1F781B18695869581700E948007F2
-:1005800080E098E00E94DA01812F8A95F1F781B12D
-:100590008695869581700E94800780E09CE00E948D
-:1005A000DA011A95F1F781B18695869581700E94DE
-:1005B000800780E090E00E94DA011F9108951F9269
-:1005C0000F920FB60F9211242F933F934F935F9387
-:1005D0006F937F938F939F93AF93BF93EF93FF930B
-:1005E0005F9B05C08CB10E94BD075F99FBCFFF9157
-:1005F000EF91BF91AF919F918F917F916F915F919B
-:100600004F913F912F910F900FBE0F901F90189513
-:100610002F923F924F925F926F927F928F929F9212
-:10062000AF92BF92CF92DF92EF92FF920F931F9300
-:10063000DF93CF93CDB7DEB76E970FB6F894DEBFDA
-:100640000FBECDBF78940E941E0787B3806C87BB16
-:1006500087EB809361001FEF1093620012981A9A43
-:1006600012BB11BA80E090E00E94DA011ABB14BB01
-:1006700087B3886187BB88B3886188BBC798C698F1
-:100680000E94690780E060E070E00E9498072224E1
-:10069000239438EC432E512C8FB589628FBD2EBC2C
-:1006A00021E030E040E050E0E0E060E070E0809188
-:1006B0000B01882309F041C08FB589628FBD2EBC24
-:1006C000203187E2380780E0480780E0580708F4C7
-:1006D0006FC0EE2309F076C06F5F7F4F6E367105F5
-:1006E0000CF0E1E06436710534F06456704079BD79
-:1006F00068BD6C597F4FEE2309F45FC08EE690E031
-:10070000861B970B853191050CF057C08B309105F6
-:100710002CF024E130E0281B390BC901880F991F08
-:10072000909379008093780020E030E040E050E042
-:1007300080910B01882309F4BFCF10920B01109216
-:10074000790010927800809178009091790099BD9D
-:1007500088BD88B599B58FBD35E03EBD80910C014F
-:10076000833109F456C18431B8F5893009F41DC1CB
-:100770008A3008F083C0863009F46CC18730D1F12B
-:10078000853009F089CF80E065E070E00E9498072D
-:1007900082E00E9480078CEF0E94800787E00E9421
-:1007A00080078CEF0E94800787E00E94800774CF4B
-:1007B0002F5F3F4F4F4F5F4F7ACF20E030E040E058
-:1007C00050E075CF6150704009F08CCF20E030E0F0
-:1007D00040E050E0E0E06BCF853209F4B5C28632EC
-:1007E000D8F5833209F4B0C2843208F0D6C182321F
-:1007F00009F052CFE0900D01F0900E0190910F01A1
-:10080000809110018A831982092F10E089819A81D1
-:10081000082B192BC69A88E0B8010E949807011589
-:100820001105A1F0FC821B82FF24EB81FC81EE2AE2
-:10083000FF2AC7010E94EA010E9480070150104070
-:100840000894E11CF11C0115110599F780E090E076
-:100850000E94DA01C69820CF873209F443C187325B
-:1008600008F49BC1883209F4FBC08E3F09F014CF15
-:10087000F89414BEE0E0F8EF09950ECF8D30D1F179
-:100880008131A9F18B3009F007CFE0900D01F09094
-:100890000E0190910F01809110018A8B198A092F06
-:1008A00010E029893A89022B132BC69A8CE0B801F3
-:1008B0000E9498070115110549F2FC8A1B8AFF2442
-:1008C0008B899C89E82AF92AC7010E9426020E9486
-:1008D0008007015010400894E11CF11C011511051E
-:1008E00099F780E090E00E94DA01C698D5CE0E9488
-:1008F0009E02D2CE30910D0120910E0190910F01F8
-:10090000809110018A8F198EE92EFF24898D9A8D8E
-:10091000E82AF92AC79AE114F10409F43FC02C8FA0
-:100920001B8E032F10E0EB8DFC8D0E2B1F2BCC2488
-:10093000DD24F601E35FFE4F9481809162008E7F9B
-:100940008093620080916200826080936200FFEF7A
-:10095000F1BB92BBC601800F911F0E94DA0180910A
-:1009600062008B7F8093620082E08A95F1F780912C
-:1009700062008460809362002FEF22BB11BA80E096
-:1009800090E00E94DA0180916200816080936200B1
-:100990000894C11CD11CEC14FD0459F6C7988EE0D4
-:1009A00060E070E00E94980777CE30910D012091B1
-:1009B0000E0190910F01809110018A871986E92E0E
-:1009C000FF24E985FA85EE2AFF2AC79AE114F1048B
-:1009D000C9F02C871B86032F10E02B853C85022B4A
-:1009E000132BCC24DD24F601E35FFE4FC601800FFC
-:1009F000911F64810E9447020894C11CD11CCE142F
-:100A0000DF0489F7C7988AE060E070E00E949807E9
-:100A100043CEC79AC69A809162008E7F809362000F
-:100A20008091620082608093620028EE33E0C20110
-:100A30000197F1F721503040D1F780916200816039
-:100A400080936200C798C69884E160E070E00E94DD
-:100A5000980722CE81E060E070E00E9498071CCEEB
-:100A600030910D0120910E0190910F0180911001A4
-:100A70008E8B1D8AE92EFF24ED89FE89EE2AFF2A3E
-:100A8000C69AE114F10409F4CFC1288F1F8AC32E3E
-:100A9000DD242F89388DC22AD32A00E010E0C60158
-:100AA0000E942602682FC8010E946D088C010894DC
-:100AB000E108F1080894C11CD11CE114F10479F794
-:100AC000F82E80E090E00E94DA018CE062E070E0B5
-:100AD0000E9498078F2D0E948007812F0E94800717
-:100AE000C698DACD90910D0180910E018E831D8202
-:100AF000E92EFF242D813E81E22AF32A90910F01F5
-:100B00008091100188871F82092F10E08F819885BE
-:100B1000082B192BC69A9FEF92BB11BA80916200E5
-:100B2000806880936200809162008160809362009F
-:100B3000F7FC65C1809162008260809362000115BC
-:100B4000110509F465C180E090E0EBBAF5BA22E046
-:100B50002A95F1F760B30E946D0801501040089487
-:100B6000E11CF11C0115110581F7182F092F809147
-:100B7000620082608093620080E090E00E94DA016F
-:100B800088E062E070E00E949807812F0E94800751
-:100B9000802F0E948007C6987FCD30910D01209153
-:100BA0000E0190910F01809110018E871D86092FF3
-:100BB00010E08D859E85082B192BC79A011511050C
-:100BC00009F435C1288B1F86E32FF0E02F85388983
-:100BD000E22BF32BFE8FED8F81E1882E81E0982EA2
-:100BE0003324662477242D8D3E8D207CAD8CBE8CE5
-:100BF0006401FF2405C0C501807C2817390781F4F2
-:100C0000F60180818F3F09F0F3940894A11CB11C78
-:100C1000015010400894C11CD11C0115110559F751
-:100C2000FF2041F40115110509F401C1BE8EAD8EFE
-:100C30004601D9CF80E090E860EF0E9447028AEA3F
-:100C40009AE86AEA0E94470285E595E865E50E9410
-:100C5000470280E090E865E20E9447026F2D6150F4
-:100C600080E090E80E94470209C02D8D3E8D2F5FE5
-:100C70003F4F3E8F2D8F0894811C911CF4016081A1
-:100C80006F3F51F08D8D9E8D90680E944702F40158
-:100C90003080FA946D8C7E8CFF2039F780E090E8EC
-:100CA00069E20E9447021DBC1CBCC30190689E8F74
-:100CB0008D8F8CB59DB584589E4108F03EC08D8DBA
-:100CC0009E8D0E94EA01E82E8D8D9E8D0E94EA0184
-:100CD000F82E8D8D9E8D0E94EA01982E8F2D8E25E7
-:100CE00086FF18C0892D8F2586FF14C0E1FC93C0B4
-:100CF000E5FEDFCF8AE263E070E00E9498078E2D68
-:100D00000E9480078F2D0E948007892D0E948007F6
-:100D1000C798C2CC8D8D9E8D0E94EA01F82E8D8DD4
-:100D20009E8D0E94EA01F81621F63F1409F47ACF4D
-:100D30008CB59DB584589E4110F28AE260E070E067
-:100D40000E949807C798A8CCC79A80E090E860EF07
-:100D50000E9447028AEA9AE86AEA0E94470285E509
-:100D600095E865E50E9447028AEA9AE860E80E94F1
-:100D700047028AEA9AE86AEA0E94470285E595E80E
-:100D800065E50E94470280E090E860E30E94470228
-:100D90001DBC1CBC8CB59DB58D589B45E8F4EE245C
-:100DA000EA94FE2C02C0E12EFF2480E090E80E942D
-:100DB000EA01182F8FEFE8168FEFF80641F0812F28
-:100DC00090E0EFEFEE22FF248E159F0561F08CB5C9
-:100DD0009DB58D589B4538F38CE260E070E00E9431
-:100DE0009807C79859CC1F3FC1F08BE261E070E0D3
-:100DF0000E949807812F0E948007C7984DCC809150
-:100E000062008D7F809362000115110509F09BCE71
-:100E100010E000E0ACCE89E26ECF8AE060E070E0E6
-:100E20000E949807C79838CCFF2410E04ACE8AE089
-:100E300060E070E00E949807C7982ECC81E089B9E5
-:100E40001092900088E98AB9E5E9F0E08081866037
-:100E5000808308955D9BFECF8CB90895982F92955D
-:100E60009F709A3070F4905D8F708A3040F4805D8E
-:100E70005D9BFECF9CB95D9BFECF8CB90895895CCC
-:100E8000F7CF995CF1CFFC018081882339F05D9B1D
-:100E9000FECF8CB9319680818823C9F708959C01D3
-:100EA000411551056105710599F080E090E0A0E0E1
-:100EB000B0E0F901E80FF91FE0815D9BFECFECB9CE
-:100EC0000196A11DB11D84179507A607B70788F3E2
-:100ED0000895109206011092050110920B011092D4
-:100EE000080108951F93182F80910001612F0E941F
-:100EF000650880930001812F0E942A071F910895A1
-:100F00000E947207809103019091040101969093D1
-:100F100004018093030120910101309102018217A5
-:100F2000930709F00895809100010E942A0708950F
-:100F3000FF920F931F93F82E8B011092000186E40D
-:100F40000E9472078F2D0E947207802F0E947207E5
-:100F5000812F0E94720710930201009301011092E9
-:100F6000040110920301012B21F4809100010E94E1
-:100F70002A071F910F91FF9008951F93182F8091BA
-:100F80000801882321F0163411F01F910895109262
-:100F900008018091050190910601892B21F410929E
-:100FA000070110920B0180910701612F0E946508D3
-:100FB000282F80930701409105015091060141308F
-:100FC000510509F43FC041305105B0F4163461F0C9
-:100FD00081E08093080182E060E070E00E94980761
-:100FE00040910501509106014F5F5F4F50930601FC
-:100FF000409305011F9108954230510561F143303E
-:101000005105B1F1FA01349788E0E030F80708F0B3
-:1010100046C08091090190910A01E817F907D8F1BB
-:101020008091090190910A01E817F907E9F6222356
-:1010300009F042C081E080930B01109206011092EA
-:101040000501A3CF10930C014F5F5F4F5093060132
-:1010500040930501CFCF812F90E090930A018093B8
-:1010600009014F5F5F4F5093060140930501C2CFC6
-:101070002091090130910A01912F80E0822B932B5E
-:1010800090930A01809309014F5F5F4F50930601CF
-:1010900040930501AFCFE35FFE4F1083A5CF1092C1
-:1010A00006011092050181E08093080184E060E070
-:1010B00070E00E94980769CF81E08093080183E087
-:1010C00060E070E00E949807B8CF6827ECE8F0E095
-:1010D000E60FF11DE4918E2F0895E62FF0E0E8274A
-:1010E000F927F070EE0FFF1FE457FE4F2591349162
-:1010F000892F992728273927C9010895F894FFCF08
+:10039000CFEFD0E1DEBFCDBF1AE0A8E0B2E001C0F0
+:1003A0001D92A531B107E1F712E0A0E0B1E0E0EA6B
+:1003B000F9E202C005900D92A830B107D9F70E946A
+:1003C000C4070C94CE140C9400008BBB95BB95FD18
+:1003D00006C08091620080618093620008958091E0
+:1003E00062008F7E8093620008950F931F938C01AB
+:1003F000809162008E7F80936200809162008260B3
+:10040000809362008FEF82BB11BA80916200806896
+:1004100080936200C8010E94E501809162008160C2
+:100420008093620017FD15C0809162008260809306
+:100430006200C39AC49A82E08A95F1F780B39091E2
+:100440006200926090936200C39AC49A1F910F91C8
+:100450000895809162008D7F80936200C39AC49852
+:10046000EACF0F931F9302E610E0F80120812E7F60
+:1004700020832081226020832FEF22BB11BA0E94AB
+:10048000E501F80180818F7D808382E08A95F1F714
+:1004900080B39081906290839081916090831F914E
+:1004A0000F9108950F931F938C01809162008E7FAE
+:1004B00080936200809162008260809362008FEF7F
+:1004C00081BB809162008F778093620062BBC8011C
+:1004D0000E94E50182E08A95F1F7809162008160D7
+:1004E0008093620017FD2DC080916200826080932E
+:1004F0006200C39AC49A92E0892F8A95F1F780919D
+:1005000062008E7F8093620080916200826080939F
+:100510006200C39AC49A9A95F1F78091620080684C
+:10052000809362008FEF82BB11BA80E090E00E945E
+:10053000E501809162008160809362001F910F91BC
+:100540000895809162008D7F80936200C398C49A61
+:10055000D2CFFF920F931F93CF93DF938C01F62E90
+:10056000EA011DBC1CBC069B16C08CB59DB5845908
+:100570009849C8F385E290E466E20E94520280E363
+:1005800060E070E00E94A20C80E0DF91CF911F91AB
+:100590000F91FF9008950115110531F081E390E46A
+:1005A0000E94F501F801808384E290E46F2D0E949F
+:1005B000520280E390E40E94F501982F209739F0D1
+:1005C00092959695969591708881892B88831DBC0C
+:1005D0001CBC069906C08CB59DB584599849C8F3D2
+:1005E000C9CF81E0D2CF1F920F920FB60F92112484
+:1005F0002F933F934F935F936F937F938F939F932B
+:10060000AF93BF93EF93FF935F9B05C08CB10E94A4
+:10061000C70C5F99FBCFFF91EF91BF91AF919F9175
+:100620008F917F916F915F914F913F912F910F909B
+:100630000FBE0F901F9018956F927F928F929F928E
+:10064000AF92BF92CF92DF92EF92FF920F931F93E0
+:10065000DF93CF930F92CDB7DEB75C016B017901C9
+:100660008A011982C79A85E290E465E20E945202EB
+:1006700082E390E40E94F50185E290E461E20E9449
+:100680005202970185E7203338070CF06EC0B7019E
+:10069000882777FD8095982F20E432E44FE050E0E2
+:1006A0000E943B142DE43FE44BE150E00E945A14B9
+:1006B000CA01B9010E9494113B014C012BEA3AEAAC
+:1006C0004AE250E40E945E0F7B018C0120E030E0A2
+:1006D00040E85FE30E94641188230CF4C9C0C8019C
+:1006E000B70120E030E04FE753E40E9404111816F0
+:1006F0000CF0A0C0C401B30120E030E04AE754E4AC
+:100700000E9458103B014C0120E030E04AEF54E4D5
+:100710000E945E0F7B018C0120E030E040E85FE347
+:100720000E94641188230CF4ADC0C801B70120E019
+:100730003FEF4FE757E40E94041118160CF09AC0DF
+:10074000C401B30120E030E040E251E40E945E0FBA
+:100750000E94880DCB01672B61F028EC30E0F90195
+:100760003197F1F70197D9F704C081E090E0019744
+:10077000F1F784E290E460E00E94520285E290E4A6
+:1007800061EE0E94520280E090E060E88E010F5F0F
+:100790001F4FA8010E94A902C114D104A1F18981AF
+:1007A000882369F03BC00894C108D108C114D10462
+:1007B00051F18981882391F50894A11CB11C80E036
+:1007C00090E0F5016081A8010E94A902882359F7F1
+:1007D00085E290E466E20E94520280E360E070E00D
+:1007E0000E94A20C80E00F90CF91DF911F910F919A
+:1007F000FF90EF90DF90CF90BF90AF909F908F9041
+:100800007F906F90089580E090E06FEFA8010E94C4
+:10081000A9028823E9F28981882399F085E290E48E
+:1008200066E20E94520284E360E070E00E94A20C43
+:1008300080E0D9CFC801B7010E94880D6A95F1F711
+:1008400098CF85E290E461EF0E9452028AEE93E035
+:100850000197F1F71DBC1CBC82E390E40E94F501F6
+:1008600081FF13C08CB59DB584589E41A8F3B0CFCD
+:1008700061E0E4CFC801B7010E94880DCB01019768
+:10088000F1F777CF61E070E0F9CFC79881E0ABCFA7
+:100890002F923F924F925F926F927F928F929F9290
+:1008A000AF92BF92CF92DF92EF92FF920F931F937E
+:1008B000DF93CF9300D000D0CDB7DEB74C016A8371
+:1008C0005C834B831901380185E290E465E20E9464
+:1008D000520280E3C81685E7D8060CF06EC0B60158
+:1008E000882777FD8095982F20E432E44FE050E090
+:1008F0000E943B142DE43FE44BE150E00E945A1467
+:10090000CA01B9010E9494115B016C012BEA3AEA19
+:100910004AE250E40E945E0F7B018C0120E030E04F
+:1009200040E85FE30E94641188230CF4F6C0C8011C
+:10093000B70120E030E04FE753E40E94041118169D
+:100940000CF0BCC0C601B50120E030E04AE754E439
+:100950000E9458105B016C0120E030E04AEF54E443
+:100960000E945E0F7B018C0120E030E040E85FE3F5
+:100970000E94641188230CF4E4C0C801B70120E090
+:100980003FEF4FE757E40E94041118160CF0C7C060
+:10099000C601B50120E030E040E251E40E945E0F64
+:1009A0000E94880DCB01672B61F028EC30E0F90143
+:1009B0003197F1F70197D9F704C081E090E00197F2
+:1009C000F1F7EA81EE2309F071C085E290E465EE6B
+:1009D0000E9452025401CC24DD24A114B104C104AC
+:1009E000D10409F443C0EE24FF2487012E010894AA
+:1009F000411C511C0AC00894E11CF11C011D111D71
+:100A0000EA14FB040C051D0588F5C20160E0A10194
+:100A10000E94A902882391F16114710461F0FDE044
+:100A2000EF16F1040105110569F0FEE0EF16F1047F
+:100A30000105110589F0FA81FF23E9F289810E94FD
+:100A40008A0CD9CF298130E0F30180819181822BFA
+:100A5000932B91838083EFCF99808824F301808149
+:100A600091818829992991838083E5CF80E090E066
+:100A700060E0A1010E94A902882339F580E00F906F
+:100A80000F900F900F90CF91DF911F910F91FF90DA
+:100A9000EF90DF90CF90BF90AF909F908F907F901E
+:100AA0006F905F904F903F902F900895C69AB40139
+:100AB0006E5F7F4F8EE20E94A20C87CFC801B70104
+:100AC0000E94880D6A95F1F77CCF85E290E465EF8E
+:100AD0000E94520280E090E060E0A1010E94A90221
+:100AE000882361F280E390E40E94F50182958F7083
+:100AF000282F20952170EB81FC8190819223908397
+:100B0000869586958170F1019081982B9083FA816A
+:100B1000FF2369F4C69881E0B2CF61E0D3CFC8016A
+:100B2000B7010E94880DCB010197F1F74ACFEB8105
+:100B3000FC8180810E948A0CF10180810E948A0CD4
+:100B4000E9CF61E070E0EFCF3F924F925F926F92FA
+:100B50007F928F929F92AF92BF92CF92DF92EF924D
+:100B6000FF920F931F93DF93CF9300D000D000D05C
+:100B7000CDB7DEB7382EA62E942E29011E830D8305
+:100B8000370101E009831A8282E290E460E00E946A
+:100B9000520283E290E461E00E94520285E290E416
+:100BA00066E20E94520286E290E460E00E945202F5
+:100BB00080E090E06FEF0E94520283E390E40E9495
+:100BC000F501182F86E290E46FEF0E94520280E058
+:100BD00090E060E00E94520283E390E40E94F501FD
+:100BE0008F778F37E9F081E360E070E00E94A20C1C
+:100BF00026960FB6F894DEBF0FBECDBFCF91DF9122
+:100C00001F910F91FF90EF90DF90CF90BF90AF902A
+:100C10009F908F907F906F905F904F903F9008953E
+:100C2000812F90E08F779070892BE9F682E390E432
+:100C30000E94F50180FDDBC0802F8A95F1F785E2E7
+:100C400090E465E20E9452028EEF98E00197F1F77E
+:100C500085E290E466E20E94520285E290E465E259
+:100C60000E9452021DBC1CBC10E08CB59DB584587E
+:100C70009E4130F01DBC1CBC1F5F1F3008F013C12B
+:100C800082E390E40E94F50181FDEFCF992009F005
+:100C9000B4C0332009F0CBC06A2DA11061E088E315
+:100CA00090E0AE014F5F5F4F9E012E5F3F4F00E02F
+:100CB00010E0FEE3CF2EFEE6DF2EF7E0EF2EF12C64
+:100CC0000E944804882309F493CF8824A110AA9491
+:100CD0009981992321F08A81882309F4EFC0BB24EC
+:100CE000B394992309F468C08A81882309F064C009
+:100CF000AA2009F0A4C0992009F45EC01C821B82BE
+:100D0000A82DB0E0F201EA0FFB1F80818B1509F4DA
+:100D1000B2C0B31408F09BC060E080E190E0AE0187
+:100D20004F5F5F4F9E012E5F3F4F8E010D5F1F4F44
+:100D3000F2E4CF2EF3E2DF2EE12CF12C0E944804E6
+:100D4000882309F455CFA110AA94B39499819923CB
+:100D500041F28A81882329F6AA2009F07EC09920D1
+:100D600009F4BFCFA82DB0E0F201EA0FFB1F80818C
+:100D70008B1509F4D1C08B819C81B31408F075C028
+:100D800060E00196AE014F5F5F4F9E012E5F3F4FC7
+:100D900000E010E072E4C72E73E2D72EE12CF12CB4
+:100DA0000E944804882309F423CFA110AA94B39485
+:100DB0009981992309F098CF85E290E466E20E9438
+:100DC000520224EF31E048EC50E0CA010197F1F7FC
+:100DD00021503040D1F7882061F1992051F5AA20A7
+:100DE00041F586E360E070E00E94A20C01CF83E34E
+:100DF00060E070E00E94A20CFBCEF20180818823AB
+:100E000009F047CFED81FE8100811181C301B80156
+:100E100020EA39ED48E050E00E941C03882309F4E1
+:100E2000E7CE600E711E9A94882483944FCF60E0C1
+:100E300036CF8FE260E070E00E94A20CD9CE1C8217
+:100E40001B82992009F05CCFB31408F465CF6A2D9A
+:100E5000AA2009F462CF61E060CF992009F082CF27
+:100E60008B819C81B31408F48BCF6A2DAA2009F4DE
+:100E700088CF61E086CFAA0FBB1FED81FE81AE0F48
+:100E8000BF1F0D911C91C301B8012DEF35E440E067
+:100E900050E00E941C03882309F4AACE600E711E44
+:100EA00083949A9450CF85E290E466E20E945202C5
+:100EB00080E360E070E00E94A20C9ACEAA2009F0C4
+:100EC00043C0992009F40BCFA82DB0E0F201EA0F3E
+:100ED000FB1F8081813009F43FC091E09315B8F584
+:100EE00060E082E090E0AE014F5F5F4F9E012E5FB9
+:100EF0003F4F00E010E072E4C72E73E2D72EE12CE2
+:100F0000F12C0E944804882309F472CEA110AA94FF
+:100F100002E0B02E9981E5CEAA0FBB1F8D819E8184
+:100F2000A80FB91F0D911C91C301B8012DEF35E435
+:100F300040E050E00E941C03882309F459CE600E63
+:100F4000711E83949A9431CF992039F2BDCF6A2DC6
+:100F5000AA2039F261E0C5CFAA0FBB1F8D819E8107
+:100F6000A80FB91F0D911C91C301B8012DEF35E4F5
+:100F700040E050E00E941C03882309F439CE600E43
+:100F8000711E83949A94C2CF2F923F924F925F9298
+:100F90006F927F928F929F92AF92BF92CF92DF9289
+:100FA000EF92FF920F931F93DF93CF93CDB7DEB7EE
+:100FB0006E970FB6F894DEBF0FBECDBF78940E9437
+:100FC000280C87B3806C87BB87EB809361001FEF91
+:100FD0001093620012981A9A12BB11BA80E090E046
+:100FE0000E94E5011ABB14BB87B3886187BB88B335
+:100FF000886188BBC798C6980E94730C80E060E047
+:1010000070E00E94A20C2224239408EC402E512C64
+:101010008FB589628FBD2EBC21E030E040E050E00A
+:10102000E0E060E070E080911302882309F041C0A5
+:101030008FB589628FBD2EBC203187E2380780E0F2
+:10104000480780E0580708F471C0EE2309F078C023
+:101050006F5F7F4F6E3671050CF0E1E0643671050D
+:1010600034F06456704079BD68BD6C597F4FEE23F3
+:1010700009F461C08EE690E0861B970B85319105DF
+:101080000CF059C08B3091052CF024E130E0281B86
+:10109000390BC901880F991F9093790080937800CC
+:1010A00020E030E040E050E080911302882309F412
+:1010B000BFCF1092130210927900109278008091A5
+:1010C00078009091790099BD88BD88B599B58FBD9C
+:1010D00035E03EBD80911402823209F4D7C28332DA
+:1010E000C8F5893009F499C28A3008F0DBC086302F
+:1010F00009F4C6C2873009F4C9C28530A1F480E082
+:1011000065E070E00E94A20C82E00E948A0C8CEFE5
+:101110000E948A0C87E00E948A0C8CEF0E948A0C45
+:1011200087E00E948A0CC698C79872CF2F5F3F4F06
+:101130004F4F5F4F78CF20E030E040E050E073CF7A
+:101140006150704009F08ACF20E030E040E050E08C
+:10115000E0E069CF873209F45DC1883208F058C0F9
+:10116000843241F0843208F4A4C1853209F4A1C16B
+:101170008632C9F63091150220911602909117021D
+:10118000809118028E871D86492F50E08D859E859F
+:10119000482B592B5E8F4D8FC79A452B09F44CC3B2
+:1011A000288B1F86E32EFF24EF85F889EE2AFF2A7D
+:1011B000B9E18B2EB2E09B2E33246624772497016D
+:1011C000207C5701640110E005C0C501807C281710
+:1011D000390799F4F60180818F3F09F01F5F089469
+:1011E000A11CB11C4D8D5E8D415050405E8F4D8FC6
+:1011F0000894C11CD11C452B41F7112309F08DC067
+:101200002D8D3E8D232B09F417C375014601D7CFD1
+:101210008D3209F4F4C18E3208F0D0C2883209F060
+:1012200082CF309115022091160290911702809181
+:1012300018028E8B1D8AE92EFF24ED89FE89EE2A85
+:10124000FF2AC69AE114F10409F4FFC2288F1F8A0D
+:10125000032F10E02F89388D022B132BCC24DD2493
+:10126000C8010E943102682FC6010E94770D6C01EF
+:101270000894E108F1080F5F1F4FE114F10481F7B2
+:101280008C0180E090E00E94E5018CE062E070E07B
+:101290000E94A20C802F0E948A0C812F0E948A0C2F
+:1012A000C69841CF8D3009F44FC18E3008F021C26D
+:1012B0008B3009F038CF00911502109116029091F1
+:1012C0001702809118028A8B198AE92EFF24498916
+:1012D0005A89E42AF52AC69A8CE0B7010E94A20C2A
+:1012E000E114F104A1F01C8B1B8A10E08B899C890E
+:1012F000082B192BC8010E9431020E948A0C089405
+:10130000E108F1080F5F1F4FE114F10499F780E045
+:1013100090E00E94E501C69806CF80E090E860EF7B
+:101320000E9452028AEA9AE86AEA0E94520285E51D
+:1013300095E865E50E94520280E090E865E20E942F
+:101340005202612F615080E090E80E94520206C074
+:101350000894E11CF11C0894811C911CF40160812B
+:101360006F3F41F0C70190680E945202F401308043
+:1013700011503701112361F780E090E869E20E9483
+:1013800052021DBC1CBC830110688CB59DB58458ED
+:101390009E41C8F5C8010E94F501E82EC8010E94CF
+:1013A000F501F82EC8010E94F501982E8F2D8E258B
+:1013B00086FF18C0892D8F2586FF14C0E1FC43C22B
+:1013C000E5FEE3CF8AE263E070E00E94A20C8E2D7E
+:1013D0000E948A0C8F2D0E948A0C892D0E948A0CF3
+:1013E000C798A1CEC8010E94F501F82EC8010E943D
+:1013F000F501F81651F63F1409F402CF8CB59DB5EE
+:1014000084589E4138F28AE260E070E00E94A20CAB
+:10141000C79889CE90911502809116028E831D8205
+:10142000E92EFF24ED81FE81EE2AFF2A909117021A
+:101430008091180288871F82092F10E02F8138853C
+:10144000022B132BC69A3FEF32BB11BA8091620078
+:101450008068809362008091620081608093620066
+:10146000F7FCDEC18091620082608093620001150A
+:10147000110509F4DEC180E090E0EBBAF5BA22E094
+:101480002A95F1F760B30E94770D0150104008943F
+:10149000E11CF11C0115110581F78C01809162009E
+:1014A00082608093620080E090E00E94E50188E025
+:1014B000EDCEC79A80E090E860EF0E9452028AEA7F
+:1014C0009AE86AEA0E94520285E595E865E50E947D
+:1014D00052028AEA9AE860E80E9452028AEA9AE88E
+:1014E0006AEA0E94520285E595E865E50E9452028B
+:1014F00080E090E860E30E9452021DBC1CBC8CB5E9
+:101500009DB58D589B45C8F40FEF1FEF02C00F2DFE
+:1015100010E080E090E80E94F501F82EFFEF0F3F09
+:101520001F0731F090E010708017910709F46BC12C
+:101530008CB59DB58D589B4550F38CE260E070E012
+:101540000E94A20CC798EFCD30911502209116028F
+:1015500090911702809118028A8F198EE92EFF242C
+:10156000498D5A8DE42AF52AC79AE114F10409F449
+:101570003FC02C8F1B8E032F10E08B8D9C8D082B72
+:10158000192BCC24DD24F601EB5EFD4F9481809174
+:1015900062008E7F809362008091620082608093FF
+:1015A0006200EFEFE1BB92BBC601800F911F0E946A
+:1015B000E501809162008B7F8093620082E08A95D2
+:1015C000F1F780916200846080936200FFEFF2BBCC
+:1015D00011BA80E090E00E94E50180916200816094
+:1015E000809362000894C11CD11CEC14FD0459F6D0
+:1015F000C7988EE060E070E00E94A20C94CD8091CC
+:1016000015026091160240E020E030E000E010E0BA
+:10161000EE24FF240E94A40586CD3091150220916E
+:10162000160290911702809118028A871986E92E76
+:10163000FF2449855A85E42AF52AC79AE114F10462
+:10164000C1F02C871B86C32EDD248B859C85C82A80
+:10165000D92A00E010E0F801EB5EFD4FC8018C0DC7
+:101660009D1D64810E9452020F5F1F4FE016F1061C
+:1016700091F7C7988AE060E070E00E94A20C53CD19
+:1016800081E060E070E00E94A20C4DCD0091150257
+:101690001091160290911702809118028A83198284
+:1016A000E92EFF2449815A81E42AF52AC69A88E066
+:1016B000B7010E94A20CE114F10409F428CE1C83A6
+:1016C0001B8210E08B819C81082B192BC8010E9482
+:1016D000F5010E948A0C0894E108F1080F5F1F4F82
+:1016E000E114F10499F780E090E00E94E501C698CA
+:1016F0001ACD813121F1833109F015CDC79AC69AEF
+:10170000809162008E7F809362008091620082608F
+:101710008093620028EE33E0C2010197F1F7215077
+:101720003040D1F780916200816080936200C79859
+:10173000C69884E160E070E00E94A20CF4CC82E1E3
+:1017400064E070E00E94A20CC69A80E090E00E94E3
+:10175000E50182E08A95F1F781B1869586958170E1
+:101760000E948A0C80E094E00E94E50182E08A9564
+:10177000F1F781B18695869581700E948A0C80E090
+:1017800098E00E94E50182E08A95F1F781B18695A3
+:10179000869581700E948A0C80E09CE00E94E501A1
+:1017A00082E08A95F1F781B18695869581700E94D5
+:1017B0008A0C80E090E00E94E501B5CC853349F0C9
+:1017C0008E3F09F0B0CCF89414BEE0E0F8EF099534
+:1017D000AACC409115020091150280911502E0916A
+:1017E000150210E00A5E1D4FF0E0EE0FFF1FE80F3C
+:1017F000F11DEA5EFD4F80E060E026E132E07F010E
+:101800000E94A40590CC3FEFF316B1F08BE261E0AB
+:1018100070E00E94A20C8F2D0E948A0CC79883CC86
+:10182000809162008D7F809362000115110509F09F
+:1018300022CE00E010E032CE8AE060E070E00E944C
+:10184000A20CC79870CC89E2BECD00E010E019CDA3
+:1018500081E089B91092900088E98AB9E5E9F0E061
+:1018600080818660808308955D9BFECF8CB908954A
+:10187000982F92959F709A3070F4905D8F708A3097
+:1018800040F4805D5D9BFECF9CB95D9BFECF8CB923
+:101890000895895CF7CF995CF1CFFC0180818823A2
+:1018A00039F05D9BFECF8CB9319680818823C9F7D2
+:1018B00008959C01411551056105710599F080E07D
+:1018C00090E0A0E0B0E0F901E80FF91FE0815D9B36
+:1018D000FECFECB90196A11DB11D84179507A6078F
+:1018E000B70788F3089510920E0210920D0210921D
+:1018F00013021092100208951F93182F809108026E
+:10190000612F0E946F0D80930802812F0E94340C7A
+:101910001F9108950E947C0C80910B0290910C0203
+:10192000019690930C0280930B0220910902309152
+:101930000A028217930709F00895809108020E9415
+:10194000340C0895FF920F931F93F82E8B01109281
+:10195000080286E40E947C0C8F2D0E947C0C802F54
+:101960000E947C0C812F0E947C0C10930A02009331
+:10197000090210920C0210920B02012B21F48091AB
+:1019800008020E94340C1F910F91FF9008951F933D
+:10199000182F80911002882321F0163411F01F9126
+:1019A00008951092100280910D0290910E02892BE1
+:1019B00021F410920F021092130280910F02612FF6
+:1019C0000E946F0D282F80930F0240910D025091BD
+:1019D0000E024130510509F43FC041305105B0F4C9
+:1019E000163461F081E08093100282E060E070E0E4
+:1019F0000E94A20C40910D0250910E024F5F5F4F6A
+:101A000050930E0240930D021F91089542305105EC
+:101A100061F143305105B1F1FA01349788E0E030CB
+:101A2000F80708F046C08091110290911202E81761
+:101A3000F907D8F18091110290911202E817F90785
+:101A4000E9F6222309F042C081E08093130210924C
+:101A50000E0210920D02A3CF109314024F5F5F4F3E
+:101A600050930E0240930D02CFCF812F90E09093C0
+:101A70001202809311024F5F5F4F50930E0240930A
+:101A80000D02C2CF2091110230911202912F80E0FD
+:101A9000822B932B90931202809311024F5F5F4F22
+:101AA00050930E0240930D02AFCFEB5EFD4F1083BB
+:101AB000A5CF10920E0210920D0281E080931002C9
+:101AC00084E060E070E00E94A20C69CF81E0809326
+:101AD000100283E060E070E00E94A20CB8CF68279B
+:101AE000ECE8F0E0E60FF11DE4918E2F0895E62F6B
+:101AF000F0E0E827F927F070EE0FFF1FE457FE4FE4
+:101B000025913491892F992728273927C9010895CC
+:101B1000EF92FF920F931F937B018C0120E030E046
+:101B200040E05FE40E94341188238CF0C801B701C3
+:101B300020E030E040E05FE40E94000F0E94F211DC
+:101B40009B01AC01205030404040504806C0C801C5
+:101B5000B7010E94F2119B01AC01B901CA011F91AA
+:101B60000F91FF90EF900895A0E0B0E0EAEBFDE068
+:101B70000C949714DC012B01FA019C91923008F42B
+:101B800039C1EB018881823008F433C1943069F4A3
+:101B9000843009F02FC111969C9111978981981773
+:101BA00009F428C1A0E0B1E025C1843009F421C1C5
+:101BB0008230A9F4923009F01DC19A01AD0188E08C
+:101BC000EA010990AE01E90109929E018150C1F735
+:101BD000E201898111969C918923818308C1923009
+:101BE00009F407C112962D903C901397EB018A815E
+:101BF0009B811496AD90BD90CD90DC901797EC80B2
+:101C0000FD800E811F819101281B390BB90137FF1F
+:101C100004C066277727621B730B603271050CF0D6
+:101C200061C0121613066CF537014801062E04C078
+:101C300096948794779467940A94D2F721E030E0E1
+:101C400040E050E004C0220F331F441F551F6A9527
+:101C5000D2F721503040404050402E213F214023B8
+:101C60005123211531054105510521F021E030E0D6
+:101C700040E050E079018A01E628F728082919296F
+:101C80003CC0232BD1F1260E371E35014601062E0E
+:101C900004C096948794779467940A94D2F721E0CD
+:101CA00030E040E050E004C0220F331F441F551FB6
+:101CB0006A95D2F721503040404050402A213B21C4
+:101CC0004C215D21211531054105510521F021E00F
+:101CD00030E040E050E059016A01A628B728C82842
+:101CE000D9280BC0821593052CF01C01AA24BB2413
+:101CF000650103C0EE24FF24870111969C91D20157
+:101D000011968C91981709F445C0992339F0A801D0
+:101D100097012A193B094C095D0906C0A6019501E6
+:101D20002E193F09400B510B57FD08C01182338219
+:101D3000228224833583468357831DC081E08183BB
+:101D40003382228288279927DC01821B930BA40B04
+:101D5000B50B84839583A683B7830DC0220F331FF1
+:101D6000441F551F24833583468357838281938183
+:101D70000197938382832481358146815781DA01DB
+:101D8000C9010197A109B1098F5F9F4FAF4FBF43B1
+:101D900028F30BC0918333822282EA0CFB1C0C1DBA
+:101DA0001D1DE482F5820683178383E080832481EE
+:101DB00035814681578157FF1AC0C901AA2797FD6F
+:101DC000A095BA2F81709070A070B070569547950D
+:101DD00037952795822B932BA42BB52B8483958342
+:101DE000A683B78382819381019693838283DF01E7
+:101DF00001C0D201CD01CDB7DEB7E2E10C94B3143E
+:101E0000A0E2B0E0E6E0FFE00C94A31469837A83DB
+:101E10008B839C832D833E834F835887E9E0EE2E8E
+:101E2000F12CEC0EFD1ECE010196B7010E946A1343
+:101E30008E010F5E1F4FCE010596B8010E946A13F6
+:101E40008A8991E089278A8BC701B801AE01475E74
+:101E50005F4F0E94B40D0E949512A096E6E00C948C
+:101E6000BF14A0E2B0E0E7E3FFE00C94A3146983A1
+:101E70007A838B839C832D833E834F835887F9E03D
+:101E8000EF2EF12CEC0EFD1ECE010196B7010E9443
+:101E90006A138E010F5E1F4FCE010596B8010E9496
+:101EA0006A13C701B801AE01475E5F4F0E94B40DCF
+:101EB0000E949512A096E6E00C94BF14A0E2B0E058
+:101EC000E4E6FFE00C94971469837A838B839C8308
+:101ED0002D833E834F835887CE010196BE01675FF5
+:101EE0007F4F0E946A13CE010596BE016F5E7F4F41
+:101EF0000E946A139985923088F089898230C8F0EF
+:101F0000943019F4823051F404C0843029F49230B2
+:101F100081F480E091E0C6C0923049F420E09A85D7
+:101F20008A89981321E02A87CE010996BBC08230A6
+:101F300049F420E09A858A89981321E02A8BCE0102
+:101F40004196B0C02D843E844F8458886D887E8829
+:101F50008F88988CEE24FF248701AA24BB24650176
+:101F600040E050E060E070E0E0E0F0E0C10181704E
+:101F70009070892BE9F0E60CF71C081D191D9A01D9
+:101F8000AB012A0D3B1D4C1D5D1D80E090E0A0E0E3
+:101F9000B0E0E614F7040805190520F481E090E0AC
+:101FA000A0E0B0E0BA01A901480F591F6A1F7B1FCA
+:101FB000AA0CBB1CCC1CDD1C97FE08C081E090E085
+:101FC000A0E0B0E0A82AB92ACA2ADB2A3196E0327A
+:101FD000F10549F0660C771C881C991C56944794AF
+:101FE00037942794C3CFFA85EA892B893C898B855E
+:101FF0009C85280F391F2E5F3F4F17C0CA01817083
+:102000009070892B61F016950795F794E79480E01E
+:1020100090E0A0E0B0E8E82AF92A0A2B1B2B76957D
+:102020006795579547952F5F3F4F77FDE7CF0CC0DA
+:10203000440F551F661F771F17FD4160EE0CFF1CF4
+:10204000001F111F21503040403090E0590790E0B0
+:10205000690790E4790760F32B8F3C8FDB01CA019D
+:102060008F779070A070B07080349105A105B10594
+:1020700061F447FD0AC0E114F1040105110529F0DE
+:10208000405C5F4F6F4F7F4F40781A8EFE1711F004
+:1020900081E08A8F4D8F5E8F6F8F78A383E0898F69
+:1020A000CE0149960E949512A096E2E10C94B314D9
+:1020B000A8E1B0E0EEE5F0E10C949F1469837A8327
+:1020C0008B839C832D833E834F835887B9E0EB2E0F
+:1020D000F12CEC0EFD1ECE010196B7010E946A1391
+:1020E0008E010F5E1F4FCE010596B8010E946A1344
+:1020F0002985223008F47EC03989323010F4B801C5
+:102100007CC08A859A8989278A87243011F02230F9
+:1021100031F4231709F06EC060E071E06EC0343016
+:1021200039F41D861E861F86188A1C861B8604C0ED
+:10213000323021F484E08987B7015FC02B853C856C
+:102140008B899C89281B390B3C872B87ED84FE8467
+:102150000F851889AD88BE88CF88D88CEA14FB0417
+:102160000C051D0540F4EE0CFF1C001F111F215033
+:1021700030403C872B8720E030E040E050E080E0BA
+:1021800090E0A0E0B0E460E070E0EA14FB040C052D
+:102190001D0540F0282B392B4A2B5B2BEA18FB0836
+:1021A0000C091D09B695A79597958795EE0CFF1C10
+:1021B000001F111F6F5F7F4F6F31710531F7DA011B
+:1021C000C9018F779070A070B07080349105A1051F
+:1021D000B10561F427FD0AC0E114F1040105110500
+:1021E00029F0205C3F4F4F4F5F4F20782D873E876F
+:1021F0004F87588BBE01675F7F4FCB010E949512BE
+:102200006896EAE00C94BB14A8E1B0E0EAE0F1E1E2
+:102210000C94A31469837A838B839C832D833E83E0
+:102220004F83588789E0E82EF12CEC0EFD1ECE017D
+:102230000196B7010E946A138E010F5E1F4FCE01F7
+:102240000596B8010E946A138985823040F0898919
+:10225000823028F0C701B8010E94E21301C08FEF5D
+:102260006896E6E00C94BF14A8E1B0E0EAE3F1E17F
+:102270000C94A31469837A838B839C832D833E8380
+:102280004F83588789E0E82EF12CEC0EFD1ECE011D
+:102290000196B7010E946A138E010F5E1F4FCE0197
+:1022A0000596B8010E946A138985823040F08989B9
+:1022B000823028F0C701B8010E94E21301C08FEFFD
+:1022C0006896E6E00C94BF14A8E1B0E0EAE6F1E11C
+:1022D0000C94A31469837A838B839C832D833E8320
+:1022E0004F83588789E0E82EF12CEC0EFD1ECE01BD
+:1022F0000196B7010E946A138E010F5E1F4FCE0137
+:102300000596B8010E946A138985823040F0898958
+:10231000823028F0C701B8010E94E21301C081E0B9
+:102320006896E6E00C94BF14A8E0B0E0EAE9F1E1B9
+:102330000C94A0149B01AC0183E08983DA01C901EC
+:102340008827B7FD83959927AA27BB27B82E211583
+:1023500031054105510519F482E089833AC088238B
+:10236000A9F0203080E0380780E0480780E858076F
+:1023700029F460E070E080E09FEC30C0EE24FF24A0
+:102380008701E21AF30A040B150B02C079018A01D6
+:102390008EE1C82ED12CDC82CB82ED82FE820F83AF
+:1023A0001887C801B7010E9446120197181619062E
+:1023B00084F4082E04C0EE0CFF1C001F111F0A94A9
+:1023C000D2F7ED82FE820F831887C81AD90ADC8201
+:1023D000CB82BA82CE0101960E9495122896E9E03E
+:1023E0000C94BC14ACE0B0E0E8EFF1E10C94A7145D
+:1023F00069837A838B839C83CE010196BE016B5FD8
+:102400007F4F0E946A138D81823061F1823050F1DA
+:10241000843021F48E81882351F12EC02F8138859C
+:1024200037FD20C06E812F3131051CF06623F9F095
+:1024300023C08EE190E0821B930B29853A854B8562
+:102440005C8504C056954795379527958A95D2F7B0
+:102450006623B1F050954095309521953F4F4F4FF1
+:102460005F4F0EC020E030E040E050E009C02FEFA9
+:102470003FEF4FEF5FE704C020E030E040E050E87E
+:10248000B901CA012C96E2E00C94C314EF92FF92BA
+:102490000F931F937B018C0180E0E81680E0F80623
+:1024A00081E0080780E0180788F48FEFE816F10450
+:1024B0000105110531F028F088E090E0A0E0B0E0DF
+:1024C00017C080E090E0A0E0B0E012C080E0E81625
+:1024D00080E0F80680E0080781E0180728F088E12E
+:1024E00090E0A0E0B0E004C080E190E0A0E0B0E0C7
+:1024F00020E230E040E050E0281B390B4A0B5B0B38
+:1025000004C016950795F794E7948A95D2F7F701DA
+:10251000E85FFE4F8081281B310941095109C9013B
+:102520001F910F91FF90EF900895DF92EF92FF922D
+:102530000F931F93FC01E480F58006811781D18001
+:102540008081823048F480E090E0A0E1B0E0E82AA9
+:10255000F92A0A2B1B2BA5C0843009F49FC08230B6
+:1025600021F4EE24FF24870105C0E114F1040105E4
+:10257000110519F4E0E0F0E096C0628173819FEFED
+:10258000623879070CF05BC022E83FEF261B370B5F
+:102590002A3131052CF020E030E040E050E02AC044
+:1025A000B801A701022E04C0769567955795479507
+:1025B0000A94D2F781E090E0A0E0B0E004C0880F78
+:1025C000991FAA1FBB1F2A95D2F70197A109B1092C
+:1025D0008E219F21A023B1230097A105B10521F0F1
+:1025E00081E090E0A0E0B0E09A01AB01282B392B0C
+:1025F0004A2B5B2BDA01C9018F779070A070B07005
+:1026000080349105A105B10539F427FF09C0205C8C
+:102610003F4F4F4F5F4F04C0215C3F4F4F4F5F4FC5
+:10262000E0E0F0E02030A0E03A07A0E04A07A0E4B4
+:102630005A0710F0E1E0F0E079018A0127C0603824
+:10264000710564F5FB01E158FF4FD801C7018F7791
+:102650009070A070B07080349105A105B10539F477
+:10266000E7FE0DC080E490E0A0E0B0E004C08FE39E
+:1026700090E0A0E0B0E0E80EF91E0A1F1B1F17FF54
+:1026800005C016950795F794E794319687E016955F
+:102690000795F794E7948A95D1F705C0EE24FF24B7
+:1026A0008701EFEFF0E06E2F679566276795902F13
+:1026B0009F77D794DD24D7948E2F8695492F462B6C
+:1026C000582F5D29B701CA011F910F91FF90EF901C
+:1026D000DF900895FC01DB01408151812281622F4E
+:1026E0006F7770E0221F2227221F9381892F880F86
+:1026F000822B282F30E0991F9927991F11969C93C0
+:10270000119721153105A9F541155105610571058F
+:1027100011F482E037C082E89FEF13969C938E936A
+:1027200012979A01AB0167E0220F331F441F551F18
+:102730006A95D1F783E08C930DC0220F331F441F9D
+:10274000551F12968D919C911397019713969C9308
+:102750008E931297203080E0380780E0480780E4AD
+:10276000580758F314962D933D934D935C93179708
+:1027700008952F3F310579F4411551056105710523
+:1027800019F484E08C93089564FF03C081E08C9376
+:1027900012C01C9210C02F57304013963C932E93BA
+:1027A000129783E08C9387E0440F551F661F771FB5
+:1027B0008A95D1F7706414964D935D936D937C93D5
+:1027C000179708951F93DC01FB019C91923008F448
+:1027D00047C08081823008F443C0943051F4119690
+:1027E0001C91843099F58181682F70E0611B71091B
+:1027F0003FC0843021F0923031F48230B9F18181D0
+:10280000882389F12DC011961C9111978230F1F027
+:1028100081811817D9F412962D913C9113978281DA
+:1028200093818217930794F028173907BCF0149608
+:102830008D919D910D90BC91A02D24813581468173
+:102840005781281739074A075B0718F4112341F00D
+:102850000AC082179307A407B50740F4112319F0A3
+:1028600061E070E005C06FEF7FEF02C060E070E0F4
+:10287000CB011F910895629FD001739FF001829F49
+:10288000E00DF11D649FE00DF11D929FF00D839FFF
+:10289000F00D749FF00D659FF00D9927729FB00D9C
+:1028A000E11DF91F639FB00DE11DF91FBD01CF01AF
+:1028B0001124089597FB092E05260ED057FD04D04C
+:1028C00014D00AD0001C38F45095409530952195CD
+:1028D0003F4F4F4F5F4F0895F6F790958095709555
+:1028E00061957F4F8F4F9F4F0895A1E21A2EAA1B2B
+:1028F000BB1BFD010DC0AA1FBB1FEE1FFF1FA217B0
+:10290000B307E407F50720F0A21BB30BE40BF50BAC
+:10291000661F771F881F991F1A9469F76095709535
+:10292000809590959B01AC01BD01CF0108952F9238
+:102930003F924F925F926F927F928F929F92AF924F
+:10294000BF92CF92DF92EF92FF920F931F93CF939C
+:10295000DF93CDB7DEB7CA1BDB0B0FB6F894DEBF33
+:102960000FBECDBF09942A88398848885F846E8459
+:102970007D848C849B84AA84B984C884DF80EE80A3
+:10298000FD800C811B81AA81B981CE0FD11D0FB6AC
+:10299000F894DEBF0FBECDBFED010895F894FFCFD0
+:1029A0000000000000000000000102020303030316
+:1029B00004040404040404040505050505050505CF
+:1029C00005050505050505050606060606060606AF
+:1029D0000606060606060606060606060606060697
+:1029E000060606060606060607070707070707077F
+:1029F0000707070707070707070707070707070767
+:102A00000707070707070707070707070707070756
+:102A10000707070707070707070707070707070746
+:102A2000070707070707070708080808080808082E
+:102A30000808080808080808080808080808080816
+:102A40000808080808080808080808080808080806
+:102A500008080808080808080808080808080808F6
+:102A600008080808080808080808080808080808E6
+:102A700008080808080808080808080808080808D6
+:102A800008080808080808080808080808080808C6
+:102A900008080808080808080808080808080808B6
+:082AA0000808080808080808EE
:00000001FF