From affbd62a54a0192f9f5f308cfef9a125a1b905cb Mon Sep 17 00:00:00 2001 From: Charles Ferguson Date: Fri, 24 Nov 2023 19:43:27 +0000 Subject: [PATCH 01/65] Replace DOS line endings; strip trailing spaces. The files appear to be formatted for DOS line endings, and had trailing spaces on some lines. These have now been stripped with: for i in *.py */*.py ; do echo $i ; sed -E -i '' 's/ *\r?$//g' $i done --- ArrayMemMapper.py | 28 +- BBCMicro/OS.py | 20 +- BBCMicro/PagedROM.py | 48 +- BBCMicro/ROM.py | 12258 +++++++++++++++++------------------ BBCMicro/Sheila.py | 33 +- BBCMicro/System.py | 56 +- CPU/AddressDispatcher.py | 189 +- CPU/Dispatch.py | 274 +- CPU/ExecutionUnit.py | 708 +- CPU/InstructionDecoder.py | 64 +- CPU/Memory.py | 186 +- CPU/Registers.py | 127 +- CPU/Writeback.py | 66 +- Debugging/Combiner.py | 20 +- Debugging/ExecutionUnit.py | 21 +- Debugging/Writeback.py | 58 +- DisassembleTest.py | 34 +- Disassembler.py | 477 +- MemoryTests.py | 199 +- ROArrayMemMapper.py | 28 +- ROMs/TestData.py | 110 +- 21 files changed, 7499 insertions(+), 7505 deletions(-) diff --git a/ArrayMemMapper.py b/ArrayMemMapper.py index b728b1c..4c03a04 100644 --- a/ArrayMemMapper.py +++ b/ArrayMemMapper.py @@ -1,15 +1,15 @@ -''' -Created on 13 Oct 2011 - -@author: chris.whitworth -''' - -class Mapper(object): - def __init__(self, data): - self.data = data - - def readByte(self, address): - return self.data[address] - - def writeByte(self, address, value): +''' +Created on 13 Oct 2011 + +@author: chris.whitworth +''' + +class Mapper(object): + def __init__(self, data): + self.data = data + + def readByte(self, address): + return self.data[address] + + def writeByte(self, address, value): self.data[address] = value \ No newline at end of file diff --git a/BBCMicro/OS.py b/BBCMicro/OS.py index 0b33d94..4f90014 100644 --- a/BBCMicro/OS.py +++ b/BBCMicro/OS.py @@ -1,11 +1,11 @@ -import ROM - -BASE = 0xc000 -TOP = 0xffff - -class MOS(object): - def readByte(self, address): - return ROM.rom_os12[address] - -def writeByte(self, address, value): +import ROM + +BASE = 0xc000 +TOP = 0xffff + +class MOS(object): + def readByte(self, address): + return ROM.rom_os12[address] + +def writeByte(self, address, value): pass \ No newline at end of file diff --git a/BBCMicro/PagedROM.py b/BBCMicro/PagedROM.py index 616b341..7b90960 100644 --- a/BBCMicro/PagedROM.py +++ b/BBCMicro/PagedROM.py @@ -1,25 +1,25 @@ -import ROM - -BASE = 0x8000 -TOP = 0xbfff - -class PagedROM(object): - def __init__(self): - self.rom = None - self.index = 0 - - def setPagedROM(self, index): - self.index = index - if index == 15: - self.rom = ROM.rom_basic2 - else: - self.rom = None - - def readByte(self, addr): - if self.rom != None: - return self.rom[addr] - else: - return 0 - - def writeByte(self, addr, value): +import ROM + +BASE = 0x8000 +TOP = 0xbfff + +class PagedROM(object): + def __init__(self): + self.rom = None + self.index = 0 + + def setPagedROM(self, index): + self.index = index + if index == 15: + self.rom = ROM.rom_basic2 + else: + self.rom = None + + def readByte(self, addr): + if self.rom != None: + return self.rom[addr] + else: + return 0 + + def writeByte(self, addr, value): pass \ No newline at end of file diff --git a/BBCMicro/ROM.py b/BBCMicro/ROM.py index cb2848b..067bed7 100644 --- a/BBCMicro/ROM.py +++ b/BBCMicro/ROM.py @@ -1,6130 +1,6130 @@ -''' -Created on 12 Oct 2011 - -@author: chris.whitworth -''' -rom_os12 = [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x00, - 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x36, 0x36, 0x7f, 0x36, 0x7f, 0x36, 0x36, 0x00, - 0x0c, 0x3f, 0x68, 0x3e, 0x0b, 0x7e, 0x18, 0x00, - 0x60, 0x66, 0x0c, 0x18, 0x30, 0x66, 0x06, 0x00, - 0x38, 0x6c, 0x6c, 0x38, 0x6d, 0x66, 0x3b, 0x00, - 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0c, 0x18, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x00, - 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, - 0x00, 0x18, 0x7e, 0x3c, 0x7e, 0x18, 0x00, 0x00, - 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, - 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, - 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, - 0x3c, 0x66, 0x6e, 0x7e, 0x76, 0x66, 0x3c, 0x00, - 0x18, 0x38, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, - 0x3c, 0x66, 0x06, 0x0c, 0x18, 0x30, 0x7e, 0x00, - 0x3c, 0x66, 0x06, 0x1c, 0x06, 0x66, 0x3c, 0x00, - 0x0c, 0x1c, 0x3c, 0x6c, 0x7e, 0x0c, 0x0c, 0x00, - 0x7e, 0x60, 0x7c, 0x06, 0x06, 0x66, 0x3c, 0x00, - 0x1c, 0x30, 0x60, 0x7c, 0x66, 0x66, 0x3c, 0x00, - 0x7e, 0x06, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x00, - 0x3c, 0x66, 0x66, 0x3c, 0x66, 0x66, 0x3c, 0x00, - 0x3c, 0x66, 0x66, 0x3e, 0x06, 0x0c, 0x38, 0x00, - 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, - 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x30, - 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, - 0x00, 0x00, 0x7e, 0x00, 0x7e, 0x00, 0x00, 0x00, - 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, - 0x3c, 0x66, 0x0c, 0x18, 0x18, 0x00, 0x18, 0x00, - 0x3c, 0x66, 0x6e, 0x6a, 0x6e, 0x60, 0x3c, 0x00, - 0x3c, 0x66, 0x66, 0x7e, 0x66, 0x66, 0x66, 0x00, - 0x7c, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x7c, 0x00, - 0x3c, 0x66, 0x60, 0x60, 0x60, 0x66, 0x3c, 0x00, - 0x78, 0x6c, 0x66, 0x66, 0x66, 0x6c, 0x78, 0x00, - 0x7e, 0x60, 0x60, 0x7c, 0x60, 0x60, 0x7e, 0x00, - 0x7e, 0x60, 0x60, 0x7c, 0x60, 0x60, 0x60, 0x00, - 0x3c, 0x66, 0x60, 0x6e, 0x66, 0x66, 0x3c, 0x00, - 0x66, 0x66, 0x66, 0x7e, 0x66, 0x66, 0x66, 0x00, - 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, - 0x3e, 0x0c, 0x0c, 0x0c, 0x0c, 0x6c, 0x38, 0x00, - 0x66, 0x6c, 0x78, 0x70, 0x78, 0x6c, 0x66, 0x00, - 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x7e, 0x00, - 0x63, 0x77, 0x7f, 0x6b, 0x6b, 0x63, 0x63, 0x00, - - 0x66, 0x66, 0x76, 0x7e, 0x6e, 0x66, 0x66, 0x00, - 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, - - 0x7c, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x00, - 0x3c, 0x66, 0x66, 0x66, 0x6a, 0x6c, 0x36, 0x00, - - 0x7c, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0x00, - 0x3c, 0x66, 0x60, 0x3c, 0x06, 0x66, 0x3c, 0x00, - - 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, - - 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x00, - 0x63, 0x63, 0x6b, 0x6b, 0x7f, 0x77, 0x63, 0x00, - - 0x66, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0x66, 0x00, - 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x00, - - 0x7e, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x7e, 0x00, - 0x7c, 0x60, 0x60, 0x60, 0x60, 0x60, 0x7c, 0x00, - - 0x00, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x00, 0x00, - 0x3e, 0x06, 0x06, 0x06, 0x06, 0x06, 0x3e, 0x00, - - 0x18, 0x3c, 0x66, 0x42, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, - - 0x1c, 0x36, 0x30, 0x7c, 0x30, 0x30, 0x7e, 0x00, - 0x00, 0x00, 0x3c, 0x06, 0x3e, 0x66, 0x3e, 0x00, - - 0x60, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x7c, 0x00, - 0x00, 0x00, 0x3c, 0x66, 0x60, 0x66, 0x3c, 0x00, - - 0x06, 0x06, 0x3e, 0x66, 0x66, 0x66, 0x3e, 0x00, - 0x00, 0x00, 0x3c, 0x66, 0x7e, 0x60, 0x3c, 0x00, - - 0x1c, 0x30, 0x30, 0x7c, 0x30, 0x30, 0x30, 0x00, - 0x00, 0x00, 0x3e, 0x66, 0x66, 0x3e, 0x06, 0x3c, - - 0x60, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x00, - 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00, - - 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x70, - 0x60, 0x60, 0x66, 0x6c, 0x78, 0x6c, 0x66, 0x00, - - 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, - 0x00, 0x00, 0x36, 0x7f, 0x6b, 0x6b, 0x63, 0x00, - - 0x00, 0x00, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x00, - 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x00, - - 0x00, 0x00, 0x7c, 0x66, 0x66, 0x7c, 0x60, 0x60, - 0x00, 0x00, 0x3e, 0x66, 0x66, 0x3e, 0x06, 0x07, - - 0x00, 0x00, 0x6c, 0x76, 0x60, 0x60, 0x60, 0x00, - 0x00, 0x00, 0x3e, 0x60, 0x3c, 0x06, 0x7c, 0x00, - - 0x30, 0x30, 0x7c, 0x30, 0x30, 0x30, 0x1c, 0x00, - 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x00, - - 0x00, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x00, - 0x00, 0x00, 0x63, 0x6b, 0x6b, 0x7f, 0x36, 0x00, - - 0x00, 0x00, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0x00, - 0x00, 0x00, 0x66, 0x66, 0x66, 0x3e, 0x06, 0x3c, - - 0x00, 0x00, 0x7e, 0x0c, 0x18, 0x30, 0x7e, 0x00, - 0x0c, 0x18, 0x18, 0x70, 0x18, 0x18, 0x0c, 0x00, - - 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00, - 0x30, 0x18, 0x18, 0x0e, 0x18, 0x18, 0x30, 0x00, - - 0x31, 0x6b, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - - 0x4c, 0x1d, 0xcb, 0x0d, 0x42, 0x42, 0x43, 0x20, - 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x72, - - 0x20, 0x00, 0x31, 0x36, 0x4b, 0x07, 0x00, 0x33, - 0x32, 0x4b, 0x07, 0x00, 0x08, 0x0d, 0x0d, 0x00, - - 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, - 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00, - - 0x55, 0xaa, 0xff, 0x11, 0x3b, 0x96, 0xa1, 0xad, - 0xb9, 0x11, 0x6f, 0xc5, 0x64, 0xf0, 0x5b, 0x59, - - 0xaf, 0x8d, 0xa6, 0xc0, 0xf9, 0xfd, 0x92, 0x39, - 0x9b, 0xeb, 0xf1, 0x39, 0x8c, 0xbd, 0x11, 0xfa, - - 0xa2, 0x79, 0x87, 0xac, 0xc5, 0x2f, 0xc5, 0xc5, - 0xc5, 0xc5, 0xc5, 0xe8, 0xc5, 0xc6, 0xc6, 0xc6, - - 0xc7, 0xc7, 0xc5, 0xc5, 0xc7, 0x4f, 0x4e, 0x5b, - 0xc8, 0xc5, 0x5f, 0x57, 0x78, 0x6b, 0xc9, 0xc5, - - 0x3c, 0x7c, 0xc7, 0x4e, 0xca, 0x00, 0x00, 0x02, - 0x80, 0x05, 0x00, 0x07, 0x80, 0x0a, 0x00, 0x0c, - - 0x80, 0x0f, 0x00, 0x11, 0x80, 0x14, 0x00, 0x16, - 0x80, 0x19, 0x00, 0x1b, 0x80, 0x1e, 0x00, 0x20, - - 0x80, 0x23, 0x00, 0x25, 0x80, 0x28, 0x00, 0x2a, - 0x80, 0x2d, 0x00, 0x2f, 0x80, 0x32, 0x00, 0x34, - - 0x80, 0x37, 0x00, 0x39, 0x80, 0x3c, 0x00, 0x3e, - 0x80, 0x41, 0x00, 0x43, 0x80, 0x46, 0x00, 0x48, - - 0x80, 0x4b, 0x00, 0x4d, 0x80, 0x00, 0x00, 0x00, - 0x28, 0x00, 0x50, 0x00, 0x78, 0x00, 0xa0, 0x00, - - 0xc8, 0x00, 0xf0, 0x01, 0x18, 0x01, 0x40, 0x01, - 0x68, 0x01, 0x90, 0x01, 0xb8, 0x01, 0xe0, 0x02, - - 0x08, 0x02, 0x30, 0x02, 0x58, 0x02, 0x80, 0x02, - 0xa8, 0x02, 0xd0, 0x02, 0xf8, 0x03, 0x20, 0x03, - - 0x48, 0x03, 0x70, 0x03, 0x98, 0x03, 0xc0, 0x1f, - 0x1f, 0x1f, 0x18, 0x1f, 0x1f, 0x18, 0x18, 0x4f, - - 0x27, 0x13, 0x4f, 0x27, 0x13, 0x27, 0x27, 0x9c, - 0xd8, 0xf4, 0x9c, 0x88, 0xc4, 0x88, 0x4b, 0x08, - - 0x10, 0x20, 0x08, 0x08, 0x10, 0x08, 0x01, 0xaa, - 0x55, 0x88, 0x44, 0x22, 0x11, 0x80, 0x40, 0x20, - - 0x10, 0x08, 0x04, 0x02, 0x01, 0x03, 0x0f, 0x01, - 0x01, 0x03, 0x01, 0x00, 0xff, 0x00, 0x00, 0xff, - - 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x0f, - 0xf0, 0xff, 0x00, 0x03, 0x0c, 0x0f, 0x30, 0x33, - - 0x3c, 0x3f, 0xc0, 0xc3, 0xcc, 0xcf, 0xf0, 0xf3, - 0xfc, 0xff, 0x07, 0x03, 0x01, 0x00, 0x07, 0x03, - - 0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0x03, 0x04, - 0x00, 0x06, 0x02, 0x0d, 0x05, 0x0d, 0x05, 0x04, - - 0x04, 0x0c, 0x0c, 0x04, 0x02, 0x32, 0x7a, 0x92, - 0xe6, 0x50, 0x40, 0x28, 0x20, 0x04, 0x30, 0x40, - - 0x58, 0x60, 0x7c, 0x28, 0x40, 0x80, 0xb5, 0x75, - 0x75, 0x0b, 0x17, 0x23, 0x2f, 0x3b, 0x7f, 0x50, - - 0x62, 0x28, 0x26, 0x00, 0x20, 0x22, 0x01, 0x07, - 0x67, 0x08, 0x7f, 0x50, 0x62, 0x28, 0x1e, 0x02, - - 0x19, 0x1b, 0x01, 0x09, 0x67, 0x09, 0x3f, 0x28, - 0x31, 0x24, 0x26, 0x00, 0x20, 0x22, 0x01, 0x07, - - 0x67, 0x08, 0x3f, 0x28, 0x31, 0x24, 0x1e, 0x02, - 0x19, 0x1b, 0x01, 0x09, 0x67, 0x09, 0x3f, 0x28, - - 0x33, 0x24, 0x1e, 0x02, 0x19, 0x1b, 0x93, 0x12, - 0x72, 0x13, 0x86, 0xd3, 0x7e, 0xd3, 0x6a, 0x74, - - 0x42, 0x4b, 0xd3, 0xd3, 0xd3, 0xd3, 0x23, 0x5f, - 0x60, 0x23, 0x04, 0x05, 0x06, 0x00, 0x01, 0x02, - - 0xae, 0x6a, 0x02, 0xd0, 0x4d, 0x24, 0xd0, 0x50, - 0x0f, 0x20, 0x68, 0xc5, 0x20, 0x6a, 0xcd, 0x30, - - 0x07, 0xc9, 0x0d, 0xd0, 0x03, 0x20, 0x18, 0xd9, - 0xc9, 0x7f, 0xf0, 0x11, 0xc9, 0x20, 0x90, 0x0f, - - 0x24, 0xd0, 0x30, 0x06, 0x20, 0xb7, 0xcf, 0x20, - 0x64, 0xc6, 0x4c, 0x5e, 0xc5, 0xa9, 0x20, 0xa8, - - 0xb9, 0x33, 0xc3, 0x8d, 0x5d, 0x03, 0xb9, 0x54, - 0xc3, 0x30, 0x4a, 0xaa, 0x09, 0xf0, 0x8d, 0x6a, - - 0x02, 0x8a, 0x4a, 0x4a, 0x4a, 0x4a, 0x18, 0x69, - 0xc3, 0x8d, 0x5e, 0x03, 0x24, 0xd0, 0x70, 0x1f, - - 0x18, 0x60, 0x9d, 0x24, 0x02, 0xe8, 0x8e, 0x6a, - 0x02, 0xd0, 0x17, 0x24, 0xd0, 0x30, 0x15, 0x70, - - 0x05, 0x20, 0xf5, 0xcc, 0x18, 0x60, 0x20, 0x68, - 0xc5, 0x20, 0x6a, 0xcd, 0x20, 0xf5, 0xcc, 0x20, - - 0x65, 0xc5, 0x18, 0x60, 0xac, 0x5e, 0x03, 0xc0, - 0xc5, 0xd0, 0xf7, 0xaa, 0xa5, 0xd0, 0x4a, 0x90, - - 0xd0, 0x8a, 0x4c, 0x1e, 0xe1, 0x8d, 0x5e, 0x03, - 0x98, 0xc9, 0x08, 0x90, 0x06, 0x49, 0xff, 0xc9, - - 0xf2, 0x49, 0xff, 0x24, 0xd0, 0x30, 0x29, 0x08, - 0x20, 0xf5, 0xcc, 0x28, 0x90, 0x03, 0xa5, 0xd0, - - 0x4a, 0x24, 0xd0, 0x50, 0xac, 0x20, 0x7a, 0xcd, - 0x08, 0x48, 0xa2, 0x18, 0xa0, 0x64, 0x20, 0xde, - - 0xcd, 0x20, 0x06, 0xcf, 0x20, 0x02, 0xca, 0xa5, - 0xd0, 0x49, 0x02, 0x85, 0xd0, 0x68, 0x28, 0x60, - - 0x49, 0x06, 0xd0, 0x08, 0xa9, 0x7f, 0x90, 0x20, - 0xa5, 0xd0, 0x29, 0x20, 0x60, 0xa0, 0x00, 0x8c, - - 0x69, 0x02, 0xa9, 0x04, 0xd0, 0x07, 0x20, 0xa2, - 0xe1, 0xa9, 0x94, 0x49, 0x95, 0x05, 0xd0, 0xd0, - - 0x09, 0x20, 0xa2, 0xe1, 0xa9, 0x0a, 0x49, 0xf4, - 0x25, 0xd0, 0x85, 0xd0, 0x60, 0xad, 0x61, 0x03, - - 0xf0, 0xfa, 0x20, 0x51, 0xc9, 0xa9, 0xdf, 0xd0, - 0xef, 0xad, 0x61, 0x03, 0xf0, 0xee, 0xa9, 0x20, - - 0x20, 0x54, 0xc9, 0xd0, 0xd8, 0x20, 0x88, 0xc5, - 0xd0, 0x55, 0xce, 0x18, 0x03, 0xae, 0x18, 0x03, - - 0xec, 0x08, 0x03, 0x30, 0x19, 0xad, 0x4a, 0x03, - 0x38, 0xed, 0x4f, 0x03, 0xaa, 0xad, 0x4b, 0x03, - - 0xe9, 0x00, 0xcd, 0x4e, 0x03, 0xb0, 0x03, 0x6d, - 0x54, 0x03, 0xa8, 0x4c, 0xf6, 0xc9, 0xad, 0x0a, - - 0x03, 0x8d, 0x18, 0x03, 0xce, 0x69, 0x02, 0x10, - 0x03, 0xee, 0x69, 0x02, 0xae, 0x19, 0x03, 0xec, - - 0x0b, 0x03, 0xf0, 0x06, 0xce, 0x19, 0x03, 0x4c, - 0xaf, 0xc6, 0x18, 0x20, 0x3f, 0xcd, 0xa9, 0x08, - - 0x24, 0xd0, 0xd0, 0x05, 0x20, 0x94, 0xc9, 0xd0, - 0x03, 0x20, 0xa4, 0xcd, 0x4c, 0xac, 0xc6, 0xa2, - - 0x00, 0x86, 0xdb, 0x20, 0x0d, 0xd1, 0xa6, 0xdb, - 0x38, 0xbd, 0x24, 0x03, 0xe9, 0x08, 0x9d, 0x24, - - 0x03, 0xb0, 0x03, 0xde, 0x25, 0x03, 0xa5, 0xda, - 0xd0, 0x1e, 0x20, 0x0d, 0xd1, 0xf0, 0x19, 0xa6, - - 0xdb, 0xbd, 0x04, 0x03, 0xe0, 0x01, 0xb0, 0x02, - 0xe9, 0x06, 0x9d, 0x24, 0x03, 0xbd, 0x05, 0x03, - - 0xe9, 0x00, 0x9d, 0x25, 0x03, 0x8a, 0xf0, 0x08, - 0x4c, 0xb8, 0xd1, 0x20, 0x88, 0xc5, 0xf0, 0x94, - - 0xa2, 0x02, 0xd0, 0x52, 0xa5, 0xd0, 0x29, 0x20, - 0xd0, 0x4a, 0xae, 0x18, 0x03, 0xec, 0x0a, 0x03, - - 0xb0, 0x12, 0xee, 0x18, 0x03, 0xad, 0x4a, 0x03, - 0x6d, 0x4f, 0x03, 0xaa, 0xad, 0x4b, 0x03, 0x69, - - 0x00, 0x4c, 0xf6, 0xc9, 0xad, 0x08, 0x03, 0x8d, - 0x18, 0x03, 0x18, 0x20, 0xe3, 0xca, 0xae, 0x19, - - 0x03, 0xec, 0x09, 0x03, 0xb0, 0x05, 0xee, 0x19, - 0x03, 0x90, 0x14, 0x20, 0x3f, 0xcd, 0xa9, 0x08, - - 0x24, 0xd0, 0xd0, 0x05, 0x20, 0xa4, 0xc9, 0xd0, - 0x03, 0x20, 0xff, 0xcd, 0x20, 0xac, 0xce, 0x20, - - 0x06, 0xcf, 0x90, 0x7e, 0xa2, 0x00, 0x86, 0xdb, - 0x20, 0x0d, 0xd1, 0xa6, 0xdb, 0x18, 0xbd, 0x24, - - 0x03, 0x69, 0x08, 0x9d, 0x24, 0x03, 0x90, 0x03, - 0xfe, 0x25, 0x03, 0xa5, 0xda, 0xd0, 0x89, 0x20, - - 0x0d, 0xd1, 0xf0, 0x84, 0xa6, 0xdb, 0xbd, 0x00, - 0x03, 0xe0, 0x01, 0x90, 0x02, 0x69, 0x06, 0x9d, - - 0x24, 0x03, 0xbd, 0x01, 0x03, 0x69, 0x00, 0x9d, - 0x25, 0x03, 0x8a, 0xf0, 0x08, 0x4c, 0xb8, 0xd1, - - 0x20, 0x88, 0xc5, 0xf0, 0x95, 0xa2, 0x02, 0x4c, - 0x21, 0xc6, 0xae, 0x55, 0x03, 0xad, 0x21, 0x03, - - 0xcd, 0x23, 0x03, 0x90, 0x53, 0xdd, 0xe7, 0xc3, - 0xf0, 0x02, 0xb0, 0x4c, 0xad, 0x22, 0x03, 0xa8, - - 0xdd, 0xef, 0xc3, 0xf0, 0x02, 0xb0, 0x41, 0x38, - 0xed, 0x20, 0x03, 0x30, 0x3b, 0xa8, 0x20, 0x88, - - 0xca, 0xa9, 0x08, 0x20, 0x9d, 0xc5, 0xa2, 0x20, - 0xa0, 0x08, 0x20, 0x8a, 0xd4, 0x20, 0xe8, 0xce, - - 0xb0, 0x47, 0x4c, 0x02, 0xca, 0xa0, 0x03, 0xb1, - 0xf0, 0x99, 0x28, 0x03, 0x88, 0x10, 0xf8, 0xa9, - - 0x28, 0x20, 0x39, 0xd8, 0xa0, 0x04, 0xd0, 0x08, - 0x2d, 0x60, 0x03, 0xaa, 0xbd, 0x6f, 0x03, 0xc8, - - 0x91, 0xf0, 0xa9, 0x00, 0xc0, 0x04, 0xd0, 0xf7, - 0x60, 0x20, 0x88, 0xc5, 0xd0, 0x5f, 0xa5, 0xd0, - - 0x29, 0x08, 0xd0, 0x03, 0x4c, 0xc1, 0xcb, 0xae, - 0x0b, 0x03, 0x8e, 0x19, 0x03, 0x20, 0xac, 0xce, - - 0xae, 0x19, 0x03, 0xec, 0x09, 0x03, 0xe8, 0x90, - 0xf1, 0x20, 0x88, 0xc5, 0xf0, 0x03, 0x4c, 0xa6, - - 0xcf, 0x8d, 0x23, 0x03, 0x8d, 0x22, 0x03, 0x20, - 0x88, 0xc5, 0xd0, 0xcc, 0x20, 0xa8, 0xc7, 0x18, - - 0xad, 0x22, 0x03, 0x6d, 0x08, 0x03, 0x8d, 0x18, - 0x03, 0xad, 0x23, 0x03, 0x18, 0x6d, 0x0b, 0x03, - - 0x8d, 0x19, 0x03, 0x20, 0xe8, 0xce, 0x90, 0x8a, - 0xa2, 0x18, 0xa0, 0x28, 0x4c, 0xde, 0xcd, 0x20, - - 0x88, 0xc5, 0xf0, 0x03, 0x4c, 0xad, 0xcf, 0x20, - 0x6e, 0xce, 0x4c, 0xaf, 0xc6, 0x20, 0xa6, 0xcf, - - 0xad, 0x61, 0x03, 0xf0, 0x33, 0xae, 0x5a, 0x03, - 0xac, 0x5c, 0x03, 0x20, 0xb3, 0xd0, 0xa2, 0x00, - - 0xa0, 0x28, 0x20, 0x7c, 0xd4, 0x38, 0xad, 0x06, - 0x03, 0xed, 0x02, 0x03, 0xa8, 0xc8, 0x8c, 0x30, - - 0x03, 0xa2, 0x2c, 0xa0, 0x28, 0x20, 0xa6, 0xd6, - 0xad, 0x2e, 0x03, 0xd0, 0x03, 0xce, 0x2f, 0x03, - - 0xce, 0x2e, 0x03, 0xce, 0x30, 0x03, 0xd0, 0xe9, - 0x60, 0xa0, 0x00, 0xf0, 0x02, 0xa0, 0x02, 0xad, - - 0x23, 0x03, 0x10, 0x01, 0xc8, 0x2d, 0x60, 0x03, - 0x85, 0xda, 0xad, 0x60, 0x03, 0xf0, 0x1c, 0x29, - - 0x07, 0x18, 0x65, 0xda, 0xaa, 0xbd, 0x23, 0xc4, - 0x99, 0x57, 0x03, 0xc0, 0x02, 0xb0, 0x0d, 0xad, - - 0x57, 0x03, 0x49, 0xff, 0x85, 0xd3, 0x4d, 0x58, - 0x03, 0x85, 0xd2, 0x60, 0xad, 0x22, 0x03, 0x99, - - 0x59, 0x03, 0x60, 0xa9, 0x20, 0x8d, 0x58, 0x03, - 0x60, 0xa2, 0x05, 0xa9, 0x00, 0x9d, 0x57, 0x03, - - 0xca, 0x10, 0xfa, 0xae, 0x60, 0x03, 0xf0, 0xeb, - 0xa9, 0xff, 0xe0, 0x0f, 0xd0, 0x02, 0xa9, 0x3f, - - 0x8d, 0x57, 0x03, 0x8d, 0x59, 0x03, 0x49, 0xff, - 0x85, 0xd2, 0x85, 0xd3, 0x8e, 0x1f, 0x03, 0xe0, - - 0x03, 0xf0, 0x11, 0x90, 0x20, 0x8e, 0x20, 0x03, - 0x20, 0x92, 0xc8, 0xce, 0x20, 0x03, 0xce, 0x1f, - - 0x03, 0x10, 0xf5, 0x60, 0xa2, 0x07, 0x8e, 0x20, - 0x03, 0x20, 0x92, 0xc8, 0x4e, 0x20, 0x03, 0xce, - - 0x1f, 0x03, 0x10, 0xf5, 0x60, 0xa2, 0x07, 0x20, - 0x8f, 0xc8, 0xa2, 0x00, 0x8e, 0x1f, 0x03, 0x8e, - - 0x20, 0x03, 0x08, 0x78, 0xad, 0x1f, 0x03, 0x2d, - 0x60, 0x03, 0xaa, 0xad, 0x20, 0x03, 0x29, 0x0f, - - 0x9d, 0x6f, 0x03, 0xa8, 0xad, 0x60, 0x03, 0x85, - 0xfa, 0xc9, 0x03, 0x08, 0x8a, 0x6a, 0x66, 0xfa, - - 0xb0, 0xfb, 0x06, 0xfa, 0x98, 0x05, 0xfa, 0xaa, - 0xa0, 0x00, 0x28, 0x08, 0xd0, 0x0e, 0x29, 0x60, - - 0xf0, 0x09, 0xc9, 0x60, 0xf0, 0x05, 0x8a, 0x49, - 0x60, 0xd0, 0x01, 0x8a, 0x20, 0x11, 0xea, 0x98, - - 0x38, 0x6d, 0x60, 0x03, 0xa8, 0x8a, 0x69, 0x10, - 0xaa, 0xc0, 0x10, 0x90, 0xdd, 0x28, 0x28, 0x60, - - 0x08, 0x2d, 0x60, 0x03, 0xaa, 0xc8, 0xb1, 0xf0, - 0x4c, 0x9e, 0xc8, 0xad, 0x23, 0x03, 0x4c, 0x33, - - 0xcb, 0xad, 0x1b, 0x03, 0xc9, 0x20, 0x90, 0x47, - 0x48, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0xaa, 0xbd, - - 0x0d, 0xc4, 0x2c, 0x67, 0x03, 0xd0, 0x20, 0x0d, - 0x67, 0x03, 0x8d, 0x67, 0x03, 0x8a, 0x29, 0x03, - - 0x18, 0x69, 0xbf, 0x85, 0xdf, 0xbd, 0x67, 0x03, - 0x85, 0xdd, 0xa0, 0x00, 0x84, 0xdc, 0x84, 0xde, - - 0xb1, 0xde, 0x91, 0xdc, 0x88, 0xd0, 0xf9, 0x68, - 0x20, 0x3e, 0xd0, 0xa0, 0x07, 0xb9, 0x1c, 0x03, - - 0x91, 0xde, 0x88, 0x10, 0xf8, 0x60, 0x68, 0x60, - 0xad, 0x1f, 0x03, 0x18, 0x6c, 0x26, 0x02, 0xc9, - - 0x01, 0x90, 0x15, 0xd0, 0xf7, 0x20, 0x88, 0xc5, - 0xd0, 0xed, 0xa9, 0x20, 0xac, 0x1c, 0x03, 0xf0, - - 0x03, 0xad, 0x5f, 0x03, 0xa0, 0x0a, 0xd0, 0x2d, - 0xad, 0x1d, 0x03, 0xac, 0x1c, 0x03, 0xc0, 0x07, - - 0x90, 0x23, 0xd0, 0x03, 0x6d, 0x90, 0x02, 0xc0, - 0x08, 0xd0, 0x07, 0x09, 0x00, 0x30, 0x03, 0x4d, - - 0x91, 0x02, 0xc0, 0x0a, 0xd0, 0x0f, 0x8d, 0x5f, - 0x03, 0xa8, 0xa5, 0xd0, 0x29, 0x20, 0x08, 0x98, - - 0xa0, 0x0a, 0x28, 0xd0, 0x06, 0x8c, 0x00, 0xfe, - 0x8d, 0x01, 0xfe, 0x60, 0xae, 0x61, 0x03, 0xf0, - - 0xa7, 0x4c, 0x60, 0xd0, 0xae, 0x50, 0x03, 0xad, - 0x51, 0x03, 0x20, 0xf8, 0xcc, 0xb0, 0x14, 0x6d, - - 0x54, 0x03, 0x90, 0x0f, 0xae, 0x50, 0x03, 0xad, - 0x51, 0x03, 0x20, 0xd4, 0xca, 0x10, 0x04, 0x38, - - 0xed, 0x54, 0x03, 0x8d, 0x51, 0x03, 0x8e, 0x50, - 0x03, 0xa0, 0x0c, 0xd0, 0x51, 0xa9, 0x00, 0xa2, - - 0x2c, 0x9d, 0x00, 0x03, 0xca, 0x10, 0xfa, 0xae, - 0x55, 0x03, 0xbc, 0xef, 0xc3, 0x8c, 0x0a, 0x03, - - 0x20, 0x88, 0xca, 0xbc, 0xe7, 0xc3, 0x8c, 0x09, - 0x03, 0xa0, 0x03, 0x8c, 0x23, 0x03, 0xc8, 0x8c, - - 0x21, 0x03, 0xce, 0x22, 0x03, 0xce, 0x20, 0x03, - 0x20, 0x39, 0xca, 0xa9, 0xf7, 0x20, 0xa8, 0xc5, - - 0xae, 0x50, 0x03, 0xad, 0x51, 0x03, 0x8e, 0x4a, - 0x03, 0x8d, 0x4b, 0x03, 0x10, 0x04, 0x38, 0xed, - - 0x54, 0x03, 0x86, 0xd8, 0x85, 0xd9, 0xae, 0x4a, - 0x03, 0xad, 0x4b, 0x03, 0xa0, 0x0e, 0x48, 0xad, - - 0x55, 0x03, 0xc9, 0x07, 0x68, 0xb0, 0x10, 0x86, - 0xda, 0x4a, 0x66, 0xda, 0x4a, 0x66, 0xda, 0x4a, - - 0x66, 0xda, 0xa6, 0xda, 0x4c, 0x2b, 0xca, 0xe9, - 0x74, 0x49, 0x20, 0x8c, 0x00, 0xfe, 0x8d, 0x01, - - 0xfe, 0xc8, 0x8c, 0x00, 0xfe, 0x8e, 0x01, 0xfe, - 0x60, 0x20, 0x81, 0xca, 0xa2, 0x1c, 0xa0, 0x2c, - - 0x20, 0x11, 0xd4, 0x0d, 0x2d, 0x03, 0x30, 0x39, - 0xa2, 0x20, 0x20, 0x49, 0xd1, 0xa2, 0x1c, 0x20, - - 0x49, 0xd1, 0xad, 0x1f, 0x03, 0x0d, 0x1d, 0x03, - 0x30, 0x27, 0xad, 0x23, 0x03, 0xd0, 0x22, 0xae, - - 0x55, 0x03, 0xad, 0x21, 0x03, 0x85, 0xda, 0xad, - 0x20, 0x03, 0x46, 0xda, 0x6a, 0x46, 0xda, 0xd0, - - 0x10, 0x6a, 0x4a, 0xdd, 0xef, 0xc3, 0xf0, 0x02, - 0x10, 0x07, 0xa0, 0x00, 0xa2, 0x1c, 0x20, 0x7c, - - 0xd4, 0xa2, 0x10, 0xa0, 0x28, 0x4c, 0xe6, 0xcd, - 0xc8, 0x98, 0xa0, 0x00, 0x8c, 0x4d, 0x03, 0x8d, - - 0x4c, 0x03, 0xad, 0x4f, 0x03, 0x4a, 0xf0, 0x09, - 0x0e, 0x4c, 0x03, 0x2e, 0x4d, 0x03, 0x4a, 0x90, - - 0xf7, 0x60, 0xa2, 0x20, 0xa0, 0x0c, 0x20, 0x8a, - 0xd4, 0x4c, 0xb8, 0xd1, 0x20, 0xc5, 0xc5, 0x20, - - 0x88, 0xc5, 0xd0, 0x13, 0xae, 0x60, 0x03, 0xf0, - 0x09, 0x85, 0xde, 0xa9, 0xc0, 0x85, 0xdf, 0x4c, - - 0xbf, 0xcf, 0xa9, 0x20, 0x4c, 0xdc, 0xcf, 0xa9, - 0x7f, 0x20, 0x3e, 0xd0, 0xae, 0x5a, 0x03, 0xa0, - - 0x00, 0x4c, 0x63, 0xcf, 0x48, 0x8a, 0x18, 0x6d, - 0x52, 0x03, 0xaa, 0x68, 0x6d, 0x53, 0x03, 0x60, - - 0x20, 0x14, 0xcb, 0x20, 0xd9, 0xe9, 0x90, 0x02, - 0x30, 0xf6, 0xa5, 0xd0, 0x49, 0x04, 0x29, 0x46, - - 0xd0, 0x2a, 0xad, 0x69, 0x02, 0x30, 0x22, 0xad, - 0x19, 0x03, 0xcd, 0x09, 0x03, 0x90, 0x1a, 0x4a, - - 0x4a, 0x38, 0x6d, 0x69, 0x02, 0x6d, 0x0b, 0x03, - 0xcd, 0x09, 0x03, 0x90, 0x0c, 0x18, 0x20, 0xd9, - - 0xe9, 0x38, 0x10, 0xfa, 0xa9, 0xff, 0x8d, 0x69, - 0x02, 0xee, 0x69, 0x02, 0x60, 0x48, 0xa2, 0x7f, - - 0xa9, 0x00, 0x85, 0xd0, 0x9d, 0xff, 0x02, 0xca, - 0xd0, 0xfa, 0x20, 0x07, 0xcd, 0x68, 0xa2, 0x7f, - - 0x8e, 0x66, 0x03, 0x2c, 0x8e, 0x02, 0x30, 0x02, - 0x09, 0x04, 0x29, 0x07, 0xaa, 0x8e, 0x55, 0x03, - - 0xbd, 0x14, 0xc4, 0x8d, 0x60, 0x03, 0xbd, 0xff, - 0xc3, 0x8d, 0x4f, 0x03, 0xbd, 0x3a, 0xc4, 0x8d, - - 0x61, 0x03, 0xd0, 0x02, 0xa9, 0x07, 0x0a, 0xa8, - 0xb9, 0x06, 0xc4, 0x8d, 0x63, 0x03, 0x0a, 0x10, - - 0xfd, 0x8d, 0x62, 0x03, 0xbc, 0x40, 0xc4, 0x8c, - 0x56, 0x03, 0xb9, 0x4f, 0xc4, 0x20, 0xf8, 0xe9, - - 0xb9, 0x4b, 0xc4, 0x20, 0xf8, 0xe9, 0xb9, 0x59, - 0xc4, 0x8d, 0x54, 0x03, 0xb9, 0x5e, 0xc4, 0x8d, - - 0x4e, 0x03, 0x98, 0x69, 0x02, 0x49, 0x07, 0x4a, - 0xaa, 0xbd, 0x66, 0xc4, 0x85, 0xe0, 0xa9, 0xc3, - - 0x85, 0xe1, 0xbd, 0x63, 0xc4, 0x8d, 0x52, 0x03, - 0x8e, 0x53, 0x03, 0xa9, 0x43, 0x20, 0xa8, 0xc5, - - 0xae, 0x55, 0x03, 0xbd, 0xf7, 0xc3, 0x20, 0x00, - 0xea, 0x08, 0x78, 0xbe, 0x69, 0xc4, 0xa0, 0x0b, - - 0xbd, 0x6e, 0xc4, 0x20, 0x5e, 0xc9, 0xca, 0x88, - 0x10, 0xf6, 0x28, 0x20, 0x39, 0xc8, 0x20, 0xbd, - - 0xc9, 0xa2, 0x00, 0xad, 0x4e, 0x03, 0x8e, 0x50, - 0x03, 0x8d, 0x51, 0x03, 0x20, 0xf6, 0xc9, 0xa0, - - 0x0c, 0x20, 0x2b, 0xca, 0xad, 0x58, 0x03, 0xae, - 0x56, 0x03, 0xbc, 0x54, 0xc4, 0x8c, 0x5d, 0x03, - - 0xa0, 0xcc, 0x8c, 0x5e, 0x03, 0xa2, 0x00, 0x8e, - 0x69, 0x02, 0x8e, 0x18, 0x03, 0x8e, 0x19, 0x03, - - 0x6c, 0x5d, 0x03, 0x20, 0x3e, 0xd0, 0xa0, 0x00, - 0xb1, 0xde, 0xc8, 0x91, 0xf0, 0xc0, 0x08, 0xd0, - - 0xf7, 0x60, 0x9d, 0x00, 0x30, 0x9d, 0x00, 0x31, - 0x9d, 0x00, 0x32, 0x9d, 0x00, 0x33, 0x9d, 0x00, - - 0x34, 0x9d, 0x00, 0x35, 0x9d, 0x00, 0x36, 0x9d, - 0x00, 0x37, 0x9d, 0x00, 0x38, 0x9d, 0x00, 0x39, - - 0x9d, 0x00, 0x3a, 0x9d, 0x00, 0x3b, 0x9d, 0x00, - 0x3c, 0x9d, 0x00, 0x3d, 0x9d, 0x00, 0x3e, 0x9d, - - 0x00, 0x3f, 0x9d, 0x00, 0x40, 0x9d, 0x00, 0x41, - 0x9d, 0x00, 0x42, 0x9d, 0x00, 0x43, 0x9d, 0x00, - - 0x44, 0x9d, 0x00, 0x45, 0x9d, 0x00, 0x46, 0x9d, - 0x00, 0x47, 0x9d, 0x00, 0x48, 0x9d, 0x00, 0x49, - - 0x9d, 0x00, 0x4a, 0x9d, 0x00, 0x4b, 0x9d, 0x00, - 0x4c, 0x9d, 0x00, 0x4d, 0x9d, 0x00, 0x4e, 0x9d, - - 0x00, 0x4f, 0x9d, 0x00, 0x50, 0x9d, 0x00, 0x51, - 0x9d, 0x00, 0x52, 0x9d, 0x00, 0x53, 0x9d, 0x00, - - 0x54, 0x9d, 0x00, 0x55, 0x9d, 0x00, 0x56, 0x9d, - 0x00, 0x57, 0x9d, 0x00, 0x58, 0x9d, 0x00, 0x59, - - 0x9d, 0x00, 0x5a, 0x9d, 0x00, 0x5b, 0x9d, 0x00, - 0x5c, 0x9d, 0x00, 0x5d, 0x9d, 0x00, 0x5e, 0x9d, - - 0x00, 0x5f, 0x9d, 0x00, 0x60, 0x9d, 0x00, 0x61, - 0x9d, 0x00, 0x62, 0x9d, 0x00, 0x63, 0x9d, 0x00, - - 0x64, 0x9d, 0x00, 0x65, 0x9d, 0x00, 0x66, 0x9d, - 0x00, 0x67, 0x9d, 0x00, 0x68, 0x9d, 0x00, 0x69, - - 0x9d, 0x00, 0x6a, 0x9d, 0x00, 0x6b, 0x9d, 0x00, - 0x6c, 0x9d, 0x00, 0x6d, 0x9d, 0x00, 0x6e, 0x9d, - - 0x00, 0x6f, 0x9d, 0x00, 0x70, 0x9d, 0x00, 0x71, - 0x9d, 0x00, 0x72, 0x9d, 0x00, 0x73, 0x9d, 0x00, - - 0x74, 0x9d, 0x00, 0x75, 0x9d, 0x00, 0x76, 0x9d, - 0x00, 0x77, 0x9d, 0x00, 0x78, 0x9d, 0x00, 0x79, - - 0x9d, 0x00, 0x7a, 0x9d, 0x00, 0x7b, 0x9d, 0x00, - 0x7c, 0x9d, 0x00, 0x7d, 0x9d, 0x00, 0x7e, 0x9d, - - 0x00, 0x7f, 0xe8, 0xf0, 0x70, 0x6c, 0x5d, 0x03, - 0x48, 0x8a, 0x38, 0xed, 0x52, 0x03, 0xaa, 0x68, - - 0xed, 0x53, 0x03, 0xcd, 0x4e, 0x03, 0x60, 0xa9, - 0x0f, 0x8d, 0x67, 0x03, 0xa9, 0x0c, 0xa0, 0x06, - - 0x99, 0x68, 0x03, 0x88, 0x10, 0xfa, 0xe0, 0x07, - 0x90, 0x02, 0xa2, 0x06, 0x8e, 0x46, 0x02, 0xad, - - 0x43, 0x02, 0xa2, 0x00, 0xec, 0x46, 0x02, 0xb0, - 0x0b, 0xbc, 0xba, 0xc4, 0x99, 0x68, 0x03, 0x69, - - 0x01, 0xe8, 0xd0, 0xf0, 0x8d, 0x44, 0x02, 0xa8, - 0xf0, 0xcc, 0xa2, 0x11, 0x4c, 0x68, 0xf1, 0xa9, - - 0x02, 0x24, 0xd0, 0xd0, 0x02, 0x50, 0x32, 0xad, - 0x09, 0x03, 0x90, 0x03, 0xad, 0x0b, 0x03, 0x70, - - 0x08, 0x8d, 0x19, 0x03, 0x68, 0x68, 0x4c, 0xaf, - 0xc6, 0x08, 0xcd, 0x65, 0x03, 0xf0, 0x19, 0x28, - - 0x90, 0x04, 0xce, 0x65, 0x03, 0x60, 0xee, 0x65, - 0x03, 0x60, 0x08, 0x48, 0xac, 0x4f, 0x03, 0x88, - - 0xd0, 0x1d, 0xad, 0x38, 0x03, 0x91, 0xd8, 0x68, - 0x28, 0x60, 0x08, 0x48, 0xac, 0x4f, 0x03, 0x88, - - 0xd0, 0x0d, 0xb1, 0xd8, 0x8d, 0x38, 0x03, 0xad, - 0x66, 0x03, 0x91, 0xd8, 0x4c, 0x77, 0xcd, 0xa9, - - 0xff, 0xc0, 0x1f, 0xd0, 0x02, 0xa9, 0x3f, 0x85, - 0xda, 0xb1, 0xd8, 0x45, 0xda, 0x91, 0xd8, 0x88, - - 0x10, 0xf7, 0x30, 0xd3, 0x20, 0x5b, 0xce, 0xad, - 0x09, 0x03, 0x8d, 0x19, 0x03, 0x20, 0x06, 0xcf, - - 0x20, 0xf8, 0xcc, 0xb0, 0x03, 0x6d, 0x54, 0x03, - 0x85, 0xdb, 0x86, 0xda, 0x85, 0xdc, 0xb0, 0x06, - - 0x20, 0x73, 0xce, 0x4c, 0xce, 0xcd, 0x20, 0xf8, - 0xcc, 0x90, 0xf5, 0x20, 0x38, 0xce, 0xa5, 0xdc, - - 0xa6, 0xda, 0x85, 0xd9, 0x86, 0xd8, 0xc6, 0xde, - 0xd0, 0xd6, 0xa2, 0x28, 0xa0, 0x18, 0xa9, 0x02, - - 0xd0, 0x06, 0xa2, 0x24, 0xa0, 0x14, 0xa9, 0x04, - 0x85, 0xda, 0xbd, 0x00, 0x03, 0x48, 0xb9, 0x00, - - 0x03, 0x9d, 0x00, 0x03, 0x68, 0x99, 0x00, 0x03, - 0xe8, 0xc8, 0xc6, 0xda, 0xd0, 0xec, 0x60, 0x20, - - 0x5b, 0xce, 0xac, 0x0b, 0x03, 0x8c, 0x19, 0x03, - 0x20, 0x06, 0xcf, 0x20, 0xd4, 0xca, 0x10, 0x04, - - 0x38, 0xed, 0x54, 0x03, 0x85, 0xdb, 0x86, 0xda, - 0x85, 0xdc, 0x90, 0x06, 0x20, 0x73, 0xce, 0x4c, - - 0x2a, 0xce, 0x20, 0xd4, 0xca, 0x30, 0xf5, 0x20, - 0x38, 0xce, 0xa5, 0xdc, 0xa6, 0xda, 0x85, 0xd9, - - 0x86, 0xd8, 0xc6, 0xde, 0xd0, 0xd5, 0xf0, 0xa2, - 0xae, 0x4d, 0x03, 0xf0, 0x10, 0xa0, 0x00, 0xb1, - - 0xda, 0x91, 0xd8, 0xc8, 0xd0, 0xf9, 0xe6, 0xd9, - 0xe6, 0xdb, 0xca, 0xd0, 0xf2, 0xac, 0x4c, 0x03, - - 0xf0, 0x08, 0x88, 0xb1, 0xda, 0x91, 0xd8, 0x98, - 0xd0, 0xf8, 0x60, 0x20, 0xda, 0xcd, 0x38, 0xad, - - 0x09, 0x03, 0xed, 0x0b, 0x03, 0x85, 0xde, 0xd0, - 0x05, 0x68, 0x68, 0x4c, 0xda, 0xcd, 0xad, 0x08, - - 0x03, 0x10, 0x70, 0xa5, 0xda, 0x48, 0x38, 0xad, - 0x0a, 0x03, 0xed, 0x08, 0x03, 0x85, 0xdf, 0xac, - - 0x4f, 0x03, 0x88, 0xb1, 0xda, 0x91, 0xd8, 0x88, - 0x10, 0xf9, 0xa2, 0x02, 0x18, 0xb5, 0xd8, 0x6d, - - 0x4f, 0x03, 0x95, 0xd8, 0xb5, 0xd9, 0x69, 0x00, - 0x10, 0x04, 0x38, 0xed, 0x54, 0x03, 0x95, 0xd9, - - 0xca, 0xca, 0xf0, 0xe8, 0xc6, 0xdf, 0x10, 0xd7, - 0x68, 0x85, 0xda, 0x60, 0xad, 0x18, 0x03, 0x48, - - 0x20, 0x6e, 0xce, 0x20, 0x06, 0xcf, 0x38, 0xad, - 0x0a, 0x03, 0xed, 0x08, 0x03, 0x85, 0xdc, 0xad, - - 0x58, 0x03, 0xac, 0x4f, 0x03, 0x88, 0x91, 0xd8, - 0xd0, 0xfb, 0x8a, 0x18, 0x6d, 0x4f, 0x03, 0xaa, - - 0xa5, 0xd9, 0x69, 0x00, 0x10, 0x04, 0x38, 0xed, - 0x54, 0x03, 0x86, 0xd8, 0x85, 0xd9, 0xc6, 0xdc, - - 0x10, 0xdd, 0x68, 0x8d, 0x18, 0x03, 0x38, 0x60, - 0xae, 0x18, 0x03, 0xec, 0x08, 0x03, 0x30, 0xf6, - - 0xec, 0x0a, 0x03, 0xf0, 0x02, 0x10, 0xef, 0xae, - 0x19, 0x03, 0xec, 0x0b, 0x03, 0x30, 0xe7, 0xec, - - 0x09, 0x03, 0xf0, 0x02, 0x10, 0xe0, 0xad, 0x19, - 0x03, 0x0a, 0xa8, 0xb1, 0xe0, 0x85, 0xd9, 0xc8, - - 0xa9, 0x02, 0x2d, 0x56, 0x03, 0x08, 0xb1, 0xe0, - 0x28, 0xf0, 0x03, 0x46, 0xd9, 0x6a, 0x6d, 0x50, - - 0x03, 0x85, 0xd8, 0xa5, 0xd9, 0x6d, 0x51, 0x03, - 0xa8, 0xad, 0x18, 0x03, 0xae, 0x4f, 0x03, 0xca, - - 0xf0, 0x12, 0xe0, 0x0f, 0xf0, 0x03, 0x90, 0x02, - 0x0a, 0x0a, 0x0a, 0x0a, 0x90, 0x02, 0xc8, 0xc8, - - 0x0a, 0x90, 0x02, 0xc8, 0x18, 0x65, 0xd8, 0x85, - 0xd8, 0x8d, 0x4a, 0x03, 0xaa, 0x98, 0x69, 0x00, - - 0x8d, 0x4b, 0x03, 0x10, 0x04, 0x38, 0xed, 0x54, - 0x03, 0x85, 0xd9, 0x18, 0x60, 0xae, 0x59, 0x03, - - 0xac, 0x5b, 0x03, 0x20, 0xb3, 0xd0, 0x20, 0x86, - 0xd4, 0xa0, 0x00, 0x84, 0xdc, 0xa4, 0xdc, 0xb1, - - 0xde, 0xf0, 0x13, 0x85, 0xdd, 0x10, 0x03, 0x20, - 0xe3, 0xd0, 0xee, 0x24, 0x03, 0xd0, 0x03, 0xee, - - 0x25, 0x03, 0x06, 0xdd, 0xd0, 0xef, 0xa2, 0x28, - 0xa0, 0x24, 0x20, 0x82, 0xd4, 0xac, 0x26, 0x03, - - 0xd0, 0x03, 0xce, 0x27, 0x03, 0xce, 0x26, 0x03, - 0xa4, 0xdc, 0xc8, 0xc0, 0x08, 0xd0, 0xcc, 0xa2, - - 0x28, 0xa0, 0x24, 0x4c, 0x8a, 0xd4, 0xa2, 0x06, - 0xa0, 0x26, 0x20, 0x82, 0xd4, 0xa2, 0x00, 0xa0, - - 0x24, 0x20, 0x82, 0xd4, 0x4c, 0xb8, 0xd1, 0xae, - 0x60, 0x03, 0xf0, 0x20, 0x20, 0x3e, 0xd0, 0xae, - - 0x60, 0x03, 0xa5, 0xd0, 0x29, 0x20, 0xd0, 0x95, - 0xa0, 0x07, 0xe0, 0x03, 0xf0, 0x20, 0xb0, 0x4e, - - 0xb1, 0xde, 0x05, 0xd2, 0x45, 0xd3, 0x91, 0xd8, - 0x88, 0x10, 0xf5, 0x60, 0xa0, 0x02, 0xd9, 0xb6, - - 0xc4, 0xf0, 0x06, 0x88, 0x10, 0xf8, 0x81, 0xd8, - 0x60, 0xb9, 0xb7, 0xc4, 0xd0, 0xf8, 0xb1, 0xde, - - 0x48, 0x4a, 0x4a, 0x4a, 0x4a, 0xaa, 0xbd, 0x1f, - 0xc3, 0x05, 0xd2, 0x45, 0xd3, 0x91, 0xd8, 0x98, - - 0x18, 0x69, 0x08, 0xa8, 0x68, 0x29, 0x0f, 0xaa, - 0xbd, 0x1f, 0xc3, 0x05, 0xd2, 0x45, 0xd3, 0x91, - - 0xd8, 0x98, 0xe9, 0x08, 0xa8, 0x10, 0xd7, 0x60, - 0x98, 0xe9, 0x21, 0x30, 0xfa, 0xa8, 0xb1, 0xde, - - 0x85, 0xdc, 0x38, 0xa9, 0x00, 0x26, 0xdc, 0xf0, - 0xef, 0x2a, 0x06, 0xdc, 0x2a, 0xaa, 0xbd, 0x2f, - - 0xc3, 0x05, 0xd2, 0x45, 0xd3, 0x91, 0xd8, 0x18, - 0x98, 0x69, 0x08, 0xa8, 0x90, 0xe5, 0x0a, 0x2a, - - 0x2a, 0x85, 0xde, 0x29, 0x03, 0x2a, 0xaa, 0x29, - 0x03, 0x69, 0xbf, 0xa8, 0xbd, 0x0d, 0xc4, 0x2c, - - 0x67, 0x03, 0xf0, 0x03, 0xbc, 0x67, 0x03, 0x84, - 0xdf, 0xa5, 0xde, 0x29, 0xf8, 0x85, 0xde, 0x60, - - 0xa2, 0x20, 0x20, 0x4d, 0xd1, 0xad, 0x1f, 0x03, - 0xc9, 0x04, 0xf0, 0x6d, 0xa0, 0x05, 0x29, 0x03, - - 0xf0, 0x0e, 0x4a, 0xb0, 0x03, 0x88, 0xd0, 0x08, - 0xaa, 0xbc, 0x5b, 0x03, 0xbd, 0x59, 0x03, 0xaa, - - 0x20, 0xb3, 0xd0, 0xad, 0x1f, 0x03, 0x30, 0x23, - 0x0a, 0x10, 0x3b, 0x29, 0xf0, 0x0a, 0xf0, 0x46, - - 0x49, 0x40, 0xf0, 0x14, 0x48, 0x20, 0xdc, 0xd0, - 0x68, 0x49, 0x60, 0xf0, 0x11, 0xc9, 0x40, 0xd0, - - 0x0a, 0xa9, 0x02, 0x85, 0xdc, 0x4c, 0x06, 0xd5, - 0x4c, 0xea, 0xd5, 0x4c, 0x38, 0xc9, 0x85, 0xdc, - - 0x4c, 0xbf, 0xd4, 0x8a, 0x19, 0x1c, 0xc4, 0x59, - 0x1d, 0xc4, 0x85, 0xd4, 0x8a, 0x19, 0x1b, 0xc4, - - 0x59, 0x20, 0xc4, 0x85, 0xd5, 0x60, 0x0a, 0x30, - 0xe2, 0x0a, 0x0a, 0x10, 0x03, 0x20, 0xeb, 0xd0, - - 0x20, 0xed, 0xd1, 0x4c, 0xd9, 0xd0, 0x20, 0xeb, - 0xd0, 0x20, 0xe2, 0xcd, 0xa0, 0x24, 0xa2, 0x20, - - 0x4c, 0x8a, 0xd4, 0xa2, 0x24, 0x20, 0x5f, 0xd8, - 0xf0, 0x06, 0x60, 0x20, 0x5d, 0xd8, 0xd0, 0x13, - - 0xac, 0x1a, 0x03, 0xa5, 0xd1, 0x25, 0xd4, 0x11, - 0xd6, 0x85, 0xda, 0xa5, 0xd5, 0x25, 0xd1, 0x45, - - 0xda, 0x91, 0xd6, 0x60, 0xb1, 0xd6, 0x05, 0xd4, - 0x45, 0xd5, 0x91, 0xd6, 0x60, 0xa2, 0x24, 0xa0, - - 0x00, 0x84, 0xda, 0xa0, 0x02, 0x20, 0x28, 0xd1, - 0x06, 0xda, 0x06, 0xda, 0xca, 0xca, 0xa0, 0x00, - - 0x20, 0x28, 0xd1, 0xe8, 0xe8, 0xa5, 0xda, 0x60, - 0xbd, 0x02, 0x03, 0xd9, 0x00, 0x03, 0xbd, 0x03, - - 0x03, 0xf9, 0x01, 0x03, 0x30, 0x10, 0xb9, 0x04, - 0x03, 0xdd, 0x02, 0x03, 0xb9, 0x05, 0x03, 0xfd, - - 0x03, 0x03, 0x10, 0x04, 0xe6, 0xda, 0xe6, 0xda, - 0x60, 0xa9, 0xff, 0xd0, 0x03, 0xad, 0x1f, 0x03, - - 0x85, 0xda, 0xa0, 0x02, 0x20, 0x76, 0xd1, 0x20, - 0xad, 0xd1, 0xa0, 0x00, 0xca, 0xca, 0x20, 0x76, - - 0xd1, 0xac, 0x61, 0x03, 0xc0, 0x03, 0xf0, 0x05, - 0xb0, 0x06, 0x20, 0xad, 0xd1, 0x20, 0xad, 0xd1, - - 0xad, 0x56, 0x03, 0xd0, 0x38, 0x60, 0x18, 0xa5, - 0xda, 0x29, 0x04, 0xf0, 0x09, 0xbd, 0x02, 0x03, - - 0x48, 0xbd, 0x03, 0x03, 0x90, 0x0e, 0xbd, 0x02, - 0x03, 0x79, 0x10, 0x03, 0x48, 0xbd, 0x03, 0x03, - - 0x79, 0x11, 0x03, 0x18, 0x99, 0x11, 0x03, 0x79, - 0x0d, 0x03, 0x9d, 0x03, 0x03, 0x68, 0x99, 0x10, - - 0x03, 0x18, 0x79, 0x0c, 0x03, 0x9d, 0x02, 0x03, - 0x90, 0x03, 0xfe, 0x03, 0x03, 0xbd, 0x03, 0x03, - - 0x0a, 0x7e, 0x03, 0x03, 0x7e, 0x02, 0x03, 0x60, - 0xa0, 0x10, 0x20, 0x88, 0xd4, 0xa2, 0x02, 0xa0, - - 0x02, 0x20, 0xd5, 0xd1, 0xa2, 0x00, 0xa0, 0x04, - 0xad, 0x61, 0x03, 0x88, 0x4a, 0xd0, 0xfc, 0xad, - - 0x56, 0x03, 0xf0, 0x01, 0xc8, 0x1e, 0x10, 0x03, - 0x3e, 0x11, 0x03, 0x88, 0xd0, 0xf7, 0x38, 0x20, - - 0xe3, 0xd1, 0xe8, 0xbd, 0x10, 0x03, 0xfd, 0x0c, - 0x03, 0x9d, 0x10, 0x03, 0x60, 0x20, 0x0d, 0xd4, - - 0xad, 0x2b, 0x03, 0x4d, 0x29, 0x03, 0x30, 0x0f, - 0xad, 0x2a, 0x03, 0xcd, 0x28, 0x03, 0xad, 0x2b, - - 0x03, 0xed, 0x29, 0x03, 0x4c, 0x14, 0xd2, 0xad, - 0x28, 0x03, 0x18, 0x6d, 0x2a, 0x03, 0xad, 0x29, - - 0x03, 0x6d, 0x2b, 0x03, 0x6a, 0xa2, 0x00, 0x4d, - 0x2b, 0x03, 0x10, 0x02, 0xa2, 0x02, 0x86, 0xde, - - 0xbd, 0xaa, 0xc4, 0x8d, 0x5d, 0x03, 0xbd, 0xab, - 0xc4, 0x8d, 0x5e, 0x03, 0xbd, 0x29, 0x03, 0x10, - - 0x04, 0xa2, 0x24, 0xd0, 0x02, 0xa2, 0x20, 0x86, - 0xdf, 0xa0, 0x2c, 0x20, 0x8a, 0xd4, 0xa5, 0xdf, - - 0x49, 0x04, 0x85, 0xdd, 0x05, 0xde, 0xaa, 0x20, - 0x80, 0xd4, 0xad, 0x1f, 0x03, 0x29, 0x10, 0x0a, - - 0x0a, 0x0a, 0x85, 0xdb, 0xa2, 0x2c, 0x20, 0x0f, - 0xd1, 0x85, 0xdc, 0xf0, 0x06, 0xa9, 0x40, 0x05, - - 0xdb, 0x85, 0xdb, 0xa6, 0xdd, 0x20, 0x0f, 0xd1, - 0x24, 0xdc, 0xf0, 0x01, 0x60, 0xa6, 0xde, 0xf0, - - 0x02, 0x4a, 0x4a, 0x29, 0x02, 0xf0, 0x07, 0x8a, - 0x09, 0x04, 0xaa, 0x20, 0x80, 0xd4, 0x20, 0x2c, - - 0xd4, 0xa5, 0xde, 0x49, 0x02, 0xaa, 0xa8, 0xad, - 0x29, 0x03, 0x4d, 0x2b, 0x03, 0x10, 0x01, 0xe8, - - 0xbd, 0xae, 0xc4, 0x8d, 0x32, 0x03, 0xbd, 0xb2, - 0xc4, 0x8d, 0x33, 0x03, 0xa9, 0x7f, 0x8d, 0x34, - - 0x03, 0x24, 0xdb, 0x70, 0x29, 0xbd, 0x47, 0xc4, - 0xaa, 0x38, 0xbd, 0x00, 0x03, 0xf9, 0x2c, 0x03, - - 0x85, 0xda, 0xbd, 0x01, 0x03, 0xf9, 0x2d, 0x03, - 0xa4, 0xda, 0xaa, 0x10, 0x03, 0x20, 0x9b, 0xd4, - - 0xaa, 0xc8, 0xd0, 0x01, 0xe8, 0x8a, 0xf0, 0x02, - 0xa0, 0x00, 0x84, 0xdf, 0xf0, 0x09, 0x8a, 0x4a, - - 0x6a, 0x09, 0x02, 0x45, 0xde, 0x85, 0xde, 0xa2, - 0x2c, 0x20, 0x64, 0xd8, 0xa6, 0xdc, 0xd0, 0x02, - - 0xc6, 0xdd, 0xca, 0xa5, 0xdb, 0xf0, 0x1f, 0x10, - 0x10, 0x2c, 0x34, 0x03, 0x10, 0x05, 0xce, 0x34, - - 0x03, 0xd0, 0x23, 0xee, 0x34, 0x03, 0x0a, 0x10, - 0x0d, 0x86, 0xdc, 0xa2, 0x2c, 0x20, 0x5f, 0xd8, - - 0xa6, 0xdc, 0x09, 0x00, 0xd0, 0x10, 0xa5, 0xd1, - 0x25, 0xd4, 0x11, 0xd6, 0x85, 0xda, 0xa5, 0xd5, - - 0x25, 0xd1, 0x45, 0xda, 0x91, 0xd6, 0x38, 0xad, - 0x35, 0x03, 0xed, 0x37, 0x03, 0x8d, 0x35, 0x03, - - 0xad, 0x36, 0x03, 0xed, 0x38, 0x03, 0xb0, 0x11, - 0x85, 0xda, 0xad, 0x35, 0x03, 0x6d, 0x39, 0x03, - - 0x8d, 0x35, 0x03, 0xa5, 0xda, 0x6d, 0x3a, 0x03, - 0x18, 0x8d, 0x36, 0x03, 0x08, 0xb0, 0x09, 0x6c, - - 0x32, 0x03, 0x88, 0x10, 0x03, 0x20, 0xd3, 0xd3, - 0x6c, 0x5d, 0x03, 0xc8, 0xc0, 0x08, 0xd0, 0xf8, - - 0x18, 0xa5, 0xd6, 0x6d, 0x52, 0x03, 0x85, 0xd6, - 0xa5, 0xd7, 0x6d, 0x53, 0x03, 0x10, 0x04, 0x38, - - 0xed, 0x54, 0x03, 0x85, 0xd7, 0xa0, 0x00, 0x6c, - 0x5d, 0x03, 0x46, 0xd1, 0x90, 0xda, 0x20, 0xed, - - 0xd3, 0x6c, 0x5d, 0x03, 0x06, 0xd1, 0x90, 0xd0, - 0x20, 0xfd, 0xd3, 0x6c, 0x5d, 0x03, 0x88, 0x10, - - 0x0c, 0x20, 0xd3, 0xd3, 0xd0, 0x07, 0x46, 0xd1, - 0x90, 0x03, 0x20, 0xed, 0xd3, 0x28, 0xe8, 0xd0, - - 0x04, 0xe6, 0xdd, 0xf0, 0x0a, 0x24, 0xdb, 0x70, - 0x07, 0xb0, 0x35, 0xc6, 0xdf, 0xd0, 0x31, 0x60, - - 0xa5, 0xde, 0x86, 0xdc, 0x29, 0x02, 0xaa, 0xb0, - 0x19, 0x24, 0xde, 0x30, 0x0a, 0xfe, 0x2c, 0x03, - - 0xd0, 0x10, 0xfe, 0x2d, 0x03, 0x90, 0x0b, 0xbd, - 0x2c, 0x03, 0xd0, 0x03, 0xde, 0x2d, 0x03, 0xde, - - 0x2c, 0x03, 0x8a, 0x49, 0x02, 0xaa, 0xfe, 0x2c, - 0x03, 0xd0, 0x03, 0xfe, 0x2d, 0x03, 0xa6, 0xdc, - - 0x4c, 0xe3, 0xd2, 0x38, 0xa5, 0xd6, 0xed, 0x52, - 0x03, 0x85, 0xd6, 0xa5, 0xd7, 0xed, 0x53, 0x03, - - 0xcd, 0x4e, 0x03, 0xb0, 0x03, 0x6d, 0x54, 0x03, - 0x85, 0xd7, 0xa0, 0x07, 0x60, 0xad, 0x62, 0x03, - - 0x85, 0xd1, 0xa5, 0xd6, 0x69, 0x07, 0x85, 0xd6, - 0x90, 0x02, 0xe6, 0xd7, 0x60, 0xad, 0x63, 0x03, - - 0x85, 0xd1, 0xa5, 0xd6, 0xd0, 0x02, 0xc6, 0xd7, - 0xe9, 0x08, 0x85, 0xd6, 0x60, 0xa0, 0x28, 0xa2, - - 0x20, 0x20, 0x18, 0xd4, 0xe8, 0xe8, 0xc8, 0xc8, - 0x38, 0xbd, 0x04, 0x03, 0xfd, 0x00, 0x03, 0x99, - - 0x00, 0x03, 0xbd, 0x05, 0x03, 0xfd, 0x01, 0x03, - 0x99, 0x01, 0x03, 0x60, 0xa5, 0xde, 0xd0, 0x07, - - 0xa2, 0x28, 0xa0, 0x2a, 0x20, 0xde, 0xcd, 0xa2, - 0x28, 0xa0, 0x37, 0x20, 0x8a, 0xd4, 0x38, 0xa6, - - 0xde, 0xad, 0x30, 0x03, 0xfd, 0x2c, 0x03, 0xa8, - 0xad, 0x31, 0x03, 0xfd, 0x2d, 0x03, 0x30, 0x03, - - 0x20, 0x9b, 0xd4, 0x85, 0xdd, 0x84, 0xdc, 0xa2, - 0x35, 0x20, 0x67, 0xd4, 0x4a, 0x9d, 0x01, 0x03, - - 0x98, 0x6a, 0x9d, 0x00, 0x03, 0xca, 0xca, 0xbc, - 0x04, 0x03, 0xbd, 0x05, 0x03, 0x10, 0x0c, 0x20, - - 0x9b, 0xd4, 0x9d, 0x05, 0x03, 0x48, 0x98, 0x9d, - 0x04, 0x03, 0x68, 0x60, 0xa9, 0x08, 0xd0, 0x0c, - - 0xa0, 0x30, 0xa9, 0x02, 0xd0, 0x06, 0xa0, 0x28, - 0xa2, 0x24, 0xa9, 0x04, 0x85, 0xda, 0xbd, 0x00, - - 0x03, 0x99, 0x00, 0x03, 0xe8, 0xc8, 0xc6, 0xda, - 0xd0, 0xf4, 0x60, 0x48, 0x98, 0x49, 0xff, 0xa8, - - 0x68, 0x49, 0xff, 0xc8, 0xd0, 0x03, 0x18, 0x69, - 0x01, 0x60, 0x20, 0x5d, 0xd8, 0xd0, 0x08, 0xb1, - - 0xd6, 0x4d, 0x5a, 0x03, 0x85, 0xda, 0x60, 0x68, - 0x68, 0xee, 0x26, 0x03, 0x4c, 0x45, 0xd5, 0x20, - - 0xaa, 0xd4, 0x25, 0xd1, 0xd0, 0xf3, 0xa2, 0x00, - 0x20, 0x92, 0xd5, 0xf0, 0x2d, 0xac, 0x1a, 0x03, - - 0x06, 0xd1, 0xb0, 0x05, 0x20, 0x74, 0xd5, 0x90, - 0x21, 0x20, 0xfd, 0xd3, 0xb1, 0xd6, 0x4d, 0x5a, - - 0x03, 0x85, 0xda, 0xd0, 0x12, 0x38, 0x8a, 0x6d, - 0x61, 0x03, 0x90, 0x04, 0xe6, 0xdb, 0x10, 0x07, - - 0xaa, 0x20, 0x04, 0xd1, 0x38, 0xb0, 0xe2, 0x20, - 0x74, 0xd5, 0xa0, 0x00, 0x20, 0xac, 0xd5, 0xa0, - - 0x20, 0xa2, 0x24, 0x20, 0xe6, 0xcd, 0x20, 0xaa, - 0xd4, 0xa2, 0x04, 0x20, 0x92, 0xd5, 0x8a, 0xd0, - - 0x02, 0xc6, 0xdb, 0xca, 0x20, 0x4b, 0xd5, 0x90, - 0x27, 0x20, 0xed, 0xd3, 0xb1, 0xd6, 0x4d, 0x5a, - - 0x03, 0x85, 0xda, 0xa5, 0xdc, 0xd0, 0xed, 0xa5, - 0xda, 0xd0, 0x12, 0x38, 0x8a, 0x6d, 0x61, 0x03, - - 0x90, 0x04, 0xe6, 0xdb, 0x10, 0x07, 0xaa, 0x20, - 0x04, 0xd1, 0x38, 0xb0, 0xdc, 0x20, 0x4b, 0xd5, - - 0xa0, 0x04, 0x20, 0xac, 0xd5, 0x20, 0xd9, 0xd0, - 0x4c, 0xb8, 0xd1, 0xa5, 0xd1, 0x48, 0x18, 0x90, - - 0x0f, 0x68, 0xe8, 0xd0, 0x04, 0xe6, 0xdb, 0x10, - 0x16, 0x46, 0xd1, 0xb0, 0x12, 0x05, 0xd1, 0x48, - - 0xa5, 0xd1, 0x24, 0xda, 0x08, 0x68, 0x45, 0xdc, - 0x48, 0x28, 0xf0, 0xe5, 0x68, 0x45, 0xd1, 0x85, - - 0xd1, 0x4c, 0xf0, 0xd0, 0xa9, 0x00, 0x18, 0x90, - 0x0a, 0xe8, 0xd0, 0x04, 0xe6, 0xdb, 0x10, 0xef, - - 0x0a, 0xb0, 0x0b, 0x05, 0xd1, 0x24, 0xda, 0xf0, - 0xf0, 0x45, 0xd1, 0x4a, 0x90, 0xe1, 0x6a, 0x38, - - 0xb0, 0xdd, 0xbd, 0x00, 0x03, 0x38, 0xed, 0x20, - 0x03, 0xa8, 0xbd, 0x01, 0x03, 0xed, 0x21, 0x03, - - 0x30, 0x03, 0x20, 0x9b, 0xd4, 0x85, 0xdb, 0x98, - 0xaa, 0x05, 0xdb, 0x60, 0x84, 0xda, 0x8a, 0xa8, - - 0xa5, 0xdb, 0x30, 0x02, 0xa9, 0x00, 0xa6, 0xda, - 0xd0, 0x03, 0x20, 0x9b, 0xd4, 0x48, 0x18, 0x98, - - 0x7d, 0x00, 0x03, 0x8d, 0x20, 0x03, 0x68, 0x7d, - 0x01, 0x03, 0x8d, 0x21, 0x03, 0x60, 0xa9, 0x03, - - 0x20, 0xd5, 0xd5, 0xa9, 0x07, 0x48, 0x20, 0xe2, - 0xcd, 0x20, 0xb8, 0xd1, 0xa2, 0x03, 0x68, 0xa8, - - 0xbd, 0x10, 0x03, 0x91, 0xf0, 0x88, 0xca, 0x10, - 0xf7, 0x60, 0xa2, 0x20, 0xa0, 0x3e, 0x20, 0x7c, - - 0xd4, 0x20, 0x32, 0xd6, 0xa2, 0x14, 0xa0, 0x24, - 0x20, 0x36, 0xd6, 0x20, 0x32, 0xd6, 0xa2, 0x20, - - 0xa0, 0x2a, 0x20, 0x11, 0xd4, 0xad, 0x2b, 0x03, - 0x8d, 0x32, 0x03, 0xa2, 0x28, 0x20, 0x59, 0xd4, - - 0xa0, 0x2e, 0x20, 0xde, 0xd0, 0x20, 0xe2, 0xcd, - 0x18, 0x20, 0x58, 0xd6, 0x20, 0xe2, 0xcd, 0xa2, - - 0x20, 0x20, 0xe4, 0xcd, 0x38, 0x20, 0x58, 0xd6, - 0xa2, 0x3e, 0xa0, 0x20, 0x20, 0x7c, 0xd4, 0x4c, - - 0xd9, 0xd0, 0xa2, 0x20, 0xa0, 0x14, 0xbd, 0x02, - 0x03, 0xd9, 0x02, 0x03, 0xbd, 0x03, 0x03, 0xf9, - - 0x03, 0x03, 0x30, 0x13, 0x4c, 0xe6, 0xcd, 0xad, - 0x18, 0x03, 0x38, 0xed, 0x08, 0x03, 0xaa, 0xad, - - 0x19, 0x03, 0x38, 0xed, 0x0b, 0x03, 0xa8, 0x60, - 0x08, 0xa2, 0x20, 0xa0, 0x35, 0x20, 0x11, 0xd4, - - 0xad, 0x36, 0x03, 0x8d, 0x3d, 0x03, 0xa2, 0x33, - 0x20, 0x59, 0xd4, 0xa0, 0x39, 0x20, 0xde, 0xd0, - - 0x38, 0xad, 0x22, 0x03, 0xed, 0x26, 0x03, 0x8d, - 0x1b, 0x03, 0xad, 0x23, 0x03, 0xed, 0x27, 0x03, - - 0x8d, 0x1c, 0x03, 0x0d, 0x1b, 0x03, 0xf0, 0x17, - 0x20, 0xa2, 0xd6, 0xa2, 0x33, 0x20, 0x74, 0xd7, - - 0xa2, 0x28, 0x20, 0x74, 0xd7, 0xee, 0x1b, 0x03, - 0xd0, 0xee, 0xee, 0x1c, 0x03, 0xd0, 0xe9, 0x28, - - 0x90, 0xb5, 0xa2, 0x39, 0xa0, 0x2e, 0x86, 0xde, - 0xbd, 0x00, 0x03, 0xd9, 0x00, 0x03, 0xbd, 0x01, - - 0x03, 0xf9, 0x01, 0x03, 0x30, 0x06, 0x98, 0xa4, - 0xde, 0xaa, 0x86, 0xde, 0x84, 0xdf, 0xb9, 0x00, - - 0x03, 0x48, 0xb9, 0x01, 0x03, 0x48, 0xa6, 0xdf, - 0x20, 0x0f, 0xd1, 0xf0, 0x0d, 0xc9, 0x02, 0xd0, - - 0x3d, 0xa2, 0x04, 0xa4, 0xdf, 0x20, 0x82, 0xd4, - 0xa6, 0xdf, 0x20, 0x64, 0xd8, 0xa6, 0xde, 0x20, - - 0x0f, 0xd1, 0x4a, 0xd0, 0x29, 0x90, 0x02, 0xa2, - 0x00, 0xa4, 0xdf, 0x38, 0xb9, 0x00, 0x03, 0xfd, - - 0x00, 0x03, 0x85, 0xdc, 0xb9, 0x01, 0x03, 0xfd, - 0x01, 0x03, 0x85, 0xdd, 0xa9, 0x00, 0x0a, 0x05, - - 0xd1, 0xa4, 0xdc, 0xd0, 0x14, 0xc6, 0xdd, 0x10, - 0x10, 0x85, 0xd1, 0x20, 0xf0, 0xd0, 0xa6, 0xdf, - - 0x68, 0x9d, 0x01, 0x03, 0x68, 0x9d, 0x00, 0x03, - 0x60, 0xc6, 0xdc, 0xaa, 0x10, 0xe0, 0x85, 0xd1, - - 0x20, 0xf0, 0xd0, 0xa6, 0xdc, 0xe8, 0xd0, 0x02, - 0xe6, 0xdd, 0x8a, 0x48, 0x46, 0xdd, 0x6a, 0xac, - - 0x61, 0x03, 0xc0, 0x03, 0xf0, 0x05, 0x90, 0x06, - 0x46, 0xdd, 0x6a, 0x46, 0xdd, 0x4a, 0xac, 0x1a, - - 0x03, 0xaa, 0xf0, 0x0f, 0x98, 0x38, 0xe9, 0x08, - 0xa8, 0xb0, 0x02, 0xc6, 0xd7, 0x20, 0x04, 0xd1, - - 0xca, 0xd0, 0xf1, 0x68, 0x2d, 0x61, 0x03, 0xf0, - 0xb5, 0xaa, 0xa9, 0x00, 0x0a, 0x0d, 0x63, 0x03, - - 0xca, 0xd0, 0xf9, 0x85, 0xd1, 0x98, 0x38, 0xe9, - 0x08, 0xa8, 0xb0, 0x02, 0xc6, 0xd7, 0x20, 0xf3, - - 0xd0, 0x4c, 0x0e, 0xd7, 0xfe, 0x08, 0x03, 0xd0, - 0x03, 0xfe, 0x09, 0x03, 0x38, 0xbd, 0x00, 0x03, - - 0xfd, 0x02, 0x03, 0x9d, 0x00, 0x03, 0xbd, 0x01, - 0x03, 0xfd, 0x03, 0x03, 0x9d, 0x01, 0x03, 0x10, - - 0x30, 0xbd, 0x0a, 0x03, 0x30, 0x0b, 0xfe, 0x06, - 0x03, 0xd0, 0x11, 0xfe, 0x07, 0x03, 0x4c, 0xac, - - 0xd7, 0xbd, 0x06, 0x03, 0xd0, 0x03, 0xde, 0x07, - 0x03, 0xde, 0x06, 0x03, 0x18, 0xbd, 0x00, 0x03, - - 0x7d, 0x04, 0x03, 0x9d, 0x00, 0x03, 0xbd, 0x01, - 0x03, 0x7d, 0x05, 0x03, 0x9d, 0x01, 0x03, 0x30, - - 0xd0, 0x60, 0xac, 0x60, 0x03, 0xd0, 0x15, 0xb1, - 0xd8, 0xa0, 0x02, 0xd9, 0xb7, 0xc4, 0xd0, 0x04, - - 0xb9, 0xb6, 0xc4, 0x88, 0x88, 0x10, 0xf4, 0xac, - 0x55, 0x03, 0xaa, 0x60, 0x20, 0x08, 0xd8, 0xa2, - - 0x20, 0x8a, 0x48, 0x20, 0x3e, 0xd0, 0x68, 0xaa, - 0xa0, 0x07, 0xb9, 0x28, 0x03, 0xd1, 0xde, 0xd0, - - 0x08, 0x88, 0x10, 0xf6, 0x8a, 0xe0, 0x7f, 0xd0, - 0xde, 0xe8, 0xa5, 0xde, 0x18, 0x69, 0x08, 0x85, - - 0xde, 0xd0, 0xe5, 0x8a, 0xd0, 0xdb, 0xf0, 0xcf, - 0xa0, 0x07, 0x84, 0xda, 0xa9, 0x01, 0x85, 0xdb, - - 0xad, 0x62, 0x03, 0x85, 0xdc, 0xb1, 0xd8, 0x4d, - 0x58, 0x03, 0x18, 0x24, 0xdc, 0xf0, 0x01, 0x38, - - 0x26, 0xdb, 0xb0, 0x0a, 0x46, 0xdc, 0x90, 0xf3, - 0x98, 0x69, 0x07, 0xa8, 0x90, 0xe2, 0xa4, 0xda, - - 0xa5, 0xdb, 0x99, 0x28, 0x03, 0x88, 0x10, 0xd2, - 0x60, 0x48, 0xaa, 0x20, 0x49, 0xd1, 0x68, 0xaa, - - 0x20, 0x5f, 0xd8, 0xd0, 0x15, 0xb1, 0xd6, 0x0a, - 0x26, 0xda, 0x06, 0xd1, 0x08, 0xb0, 0x02, 0x46, - - 0xda, 0x28, 0xd0, 0xf3, 0xa5, 0xda, 0x2d, 0x60, - 0x03, 0x60, 0xa9, 0xff, 0x60, 0xa2, 0x20, 0x20, - - 0x0f, 0xd1, 0xd0, 0xf8, 0xbd, 0x02, 0x03, 0x49, - 0xff, 0xa8, 0x29, 0x07, 0x8d, 0x1a, 0x03, 0x98, - - 0x4a, 0x4a, 0x4a, 0x0a, 0xa8, 0xb1, 0xe0, 0x85, - 0xda, 0xc8, 0xb1, 0xe0, 0xac, 0x56, 0x03, 0xf0, - - 0x03, 0x46, 0xda, 0x6a, 0x6d, 0x50, 0x03, 0x85, - 0xd6, 0xa5, 0xda, 0x6d, 0x51, 0x03, 0x85, 0xd7, - - 0xbd, 0x01, 0x03, 0x85, 0xda, 0xbd, 0x00, 0x03, - 0x48, 0x2d, 0x61, 0x03, 0x6d, 0x61, 0x03, 0xa8, - - 0xb9, 0x06, 0xc4, 0x85, 0xd1, 0x68, 0xac, 0x61, - 0x03, 0xc0, 0x03, 0xf0, 0x05, 0xb0, 0x06, 0x0a, - - 0x26, 0xda, 0x0a, 0x26, 0xda, 0x29, 0xf8, 0x18, - 0x65, 0xd6, 0x85, 0xd6, 0xa5, 0xda, 0x65, 0xd7, - - 0x10, 0x04, 0x38, 0xed, 0x54, 0x03, 0x85, 0xd7, - 0xac, 0x1a, 0x03, 0xa9, 0x00, 0x60, 0x48, 0xa9, - - 0xa0, 0xae, 0x6a, 0x02, 0xd0, 0x40, 0x24, 0xd0, - 0xd0, 0x3c, 0x70, 0x19, 0xad, 0x5f, 0x03, 0x29, - - 0x9f, 0x09, 0x40, 0x20, 0x54, 0xc9, 0xa2, 0x18, - 0xa0, 0x64, 0x20, 0x82, 0xd4, 0x20, 0x7a, 0xcd, - - 0xa9, 0x02, 0x20, 0x9d, 0xc5, 0xa9, 0xbf, 0x20, - 0xa8, 0xc5, 0x68, 0x29, 0x7f, 0x20, 0xc0, 0xc4, - - 0xa9, 0x40, 0x4c, 0x9d, 0xc5, 0xa9, 0x20, 0x24, - 0xd0, 0x50, 0xc0, 0xd0, 0xbe, 0x20, 0xc2, 0xd7, - - 0xf0, 0x05, 0x48, 0x20, 0x64, 0xc6, 0x68, 0x60, - 0xa9, 0xbd, 0x20, 0xa8, 0xc5, 0x20, 0x51, 0xc9, - - 0xa9, 0x0d, 0x60, 0xae, 0x55, 0x03, 0x8a, 0x29, - 0x07, 0xa8, 0xbe, 0x40, 0xc4, 0xbd, 0x5e, 0xc4, - - 0xa2, 0x00, 0x2c, 0x8e, 0x02, 0x30, 0x07, 0x29, - 0x3f, 0xc0, 0x04, 0xb0, 0x01, 0x8a, 0xa8, 0x60, - - 0x10, 0xe3, 0x54, 0xdc, 0x93, 0xdc, 0x89, 0xde, - 0x89, 0xdf, 0x72, 0xe7, 0xeb, 0xe7, 0xa4, 0xe0, - - 0xc5, 0xde, 0x7d, 0xf2, 0x8e, 0xf1, 0xc9, 0xf4, - 0x29, 0xf5, 0xa6, 0xff, 0xca, 0xf3, 0xb1, 0xf1, - - 0xa6, 0xff, 0xa6, 0xff, 0xa6, 0xff, 0xa6, 0xff, - 0x02, 0xef, 0xb3, 0xe4, 0x64, 0xe4, 0xd1, 0xe1, - - 0xa6, 0xff, 0xa6, 0xff, 0xa6, 0xff, 0x90, 0x01, - 0x9f, 0x0d, 0xa1, 0x02, 0x2b, 0xf0, 0x00, 0x03, - - 0x00, 0x00, 0xff, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xff, 0x04, 0x04, 0x00, 0xff, - - 0x56, 0x19, 0x19, 0x19, 0x32, 0x08, 0x00, 0x00, - 0x00, 0x00, 0x20, 0x09, 0x00, 0x00, 0x00, 0x00, - - 0x00, 0x50, 0x00, 0x03, 0x90, 0x64, 0x06, 0x81, - 0x00, 0x00, 0x00, 0x09, 0x1b, 0x01, 0xd0, 0xe0, - - 0xf0, 0x01, 0x80, 0x90, 0x00, 0x00, 0x00, 0xff, - 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - - 0x00, 0x00, 0x64, 0x05, 0xff, 0x01, 0x0a, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xa9, 0x40, 0x8d, - - 0x00, 0x0d, 0x78, 0xd8, 0xa2, 0xff, 0x9a, 0xad, - 0x4e, 0xfe, 0x0a, 0x48, 0xf0, 0x09, 0xad, 0x58, - - 0x02, 0x4a, 0xc9, 0x01, 0xd0, 0x1d, 0x4a, 0xa2, - 0x04, 0x86, 0x01, 0x85, 0x00, 0xa8, 0x91, 0x00, - - 0xc5, 0x01, 0xf0, 0x09, 0xc8, 0xd0, 0xf7, 0xc8, - 0xe8, 0xe6, 0x01, 0x10, 0xf1, 0x8e, 0x8e, 0x02, - - 0x8e, 0x84, 0x02, 0xa2, 0x0f, 0x8e, 0x42, 0xfe, - 0xca, 0x8e, 0x40, 0xfe, 0xe0, 0x09, 0xb0, 0xf8, - - 0xe8, 0x8a, 0x20, 0x2a, 0xf0, 0xe0, 0x80, 0x66, - 0xfc, 0xaa, 0xca, 0xd0, 0xf4, 0x8e, 0x8d, 0x02, - - 0x26, 0xfc, 0x20, 0xeb, 0xee, 0x6a, 0xa2, 0x9c, - 0xa0, 0x8d, 0x68, 0xf0, 0x09, 0xa0, 0x7e, 0x90, - - 0x11, 0xa0, 0x87, 0xee, 0x8d, 0x02, 0xee, 0x8d, - 0x02, 0xa5, 0xfc, 0x49, 0xff, 0x8d, 0x8f, 0x02, - - 0xa2, 0x90, 0xa9, 0x00, 0xe0, 0xce, 0x90, 0x02, - 0xa9, 0xff, 0x9d, 0x00, 0x02, 0xe8, 0xd0, 0xf4, - - 0x8d, 0x63, 0xfe, 0x8a, 0xa2, 0xe2, 0x95, 0x00, - 0xe8, 0xd0, 0xfb, 0xb9, 0x3f, 0xd9, 0x99, 0xff, - - 0x01, 0x88, 0xd0, 0xf7, 0xa9, 0x62, 0x85, 0xed, - 0x20, 0x0a, 0xfb, 0xa9, 0x7f, 0xe8, 0x9d, 0x4d, - - 0xfe, 0x9d, 0x6d, 0xfe, 0xca, 0x10, 0xf7, 0x58, - 0x78, 0x24, 0xfc, 0x50, 0x03, 0x20, 0x55, 0xf0, - - 0xa2, 0xf2, 0x8e, 0x4e, 0xfe, 0xa2, 0x04, 0x8e, - 0x4c, 0xfe, 0xa9, 0x60, 0x8d, 0x4b, 0xfe, 0xa9, - - 0x0e, 0x8d, 0x46, 0xfe, 0x8d, 0x6c, 0xfe, 0x8d, - 0xc0, 0xfe, 0xcd, 0x6c, 0xfe, 0xf0, 0x03, 0xee, - - 0x77, 0x02, 0xa9, 0x27, 0x8d, 0x47, 0xfe, 0x8d, - 0x45, 0xfe, 0x20, 0x60, 0xec, 0xad, 0x82, 0x02, - - 0x29, 0x7f, 0x20, 0xa7, 0xe6, 0xae, 0x84, 0x02, - 0xf0, 0x03, 0x20, 0xc8, 0xe9, 0x20, 0x16, 0xdc, - - 0xa2, 0x03, 0xac, 0x07, 0x80, 0xb9, 0x00, 0x80, - 0xdd, 0x0c, 0xdf, 0xd0, 0x2e, 0xc8, 0xca, 0x10, - - 0xf4, 0xa6, 0xf4, 0xa4, 0xf4, 0xc8, 0xc0, 0x10, - 0xb0, 0x25, 0x98, 0x49, 0xff, 0x85, 0xfa, 0xa9, - - 0x7f, 0x85, 0xfb, 0x8c, 0x30, 0xfe, 0xb1, 0xfa, - 0x8e, 0x30, 0xfe, 0xd1, 0xfa, 0xd0, 0xe6, 0xe6, - - 0xfa, 0xd0, 0xf0, 0xe6, 0xfb, 0xa5, 0xfb, 0xc9, - 0x84, 0x90, 0xe8, 0xa6, 0xf4, 0x10, 0x0d, 0xad, - - 0x06, 0x80, 0x9d, 0xa1, 0x02, 0x29, 0x8f, 0xd0, - 0x03, 0x8e, 0x4b, 0x02, 0xe8, 0xe0, 0x10, 0x90, - - 0xac, 0x2c, 0x40, 0xfe, 0x30, 0x11, 0xce, 0x7b, - 0x02, 0xa0, 0xff, 0x20, 0x7f, 0xee, 0xca, 0xd0, - - 0xf8, 0x8e, 0x48, 0xfe, 0x8e, 0x49, 0xfe, 0xad, - 0x8f, 0x02, 0x20, 0x00, 0xc3, 0xa0, 0xca, 0x20, - - 0xf1, 0xe4, 0x20, 0xd9, 0xea, 0x20, 0x40, 0xf1, - 0xa9, 0x81, 0x8d, 0xe0, 0xfe, 0xad, 0xe0, 0xfe, - - 0x6a, 0x90, 0x0a, 0xa2, 0xff, 0x20, 0x68, 0xf1, - 0xd0, 0x03, 0xce, 0x7a, 0x02, 0xa0, 0x0e, 0xa2, - - 0x01, 0x20, 0x68, 0xf1, 0xa2, 0x02, 0x20, 0x68, - 0xf1, 0x8c, 0x43, 0x02, 0x8c, 0x44, 0x02, 0xa2, - - 0xfe, 0xac, 0x7a, 0x02, 0x20, 0x68, 0xf1, 0x2d, - 0x67, 0x02, 0x10, 0x1b, 0xa0, 0x02, 0x20, 0xa9, - - 0xde, 0xad, 0x8d, 0x02, 0xf0, 0x0c, 0xa0, 0x16, - 0x2c, 0x8e, 0x02, 0x30, 0x02, 0xa0, 0x11, 0x20, - - 0xa9, 0xde, 0xa0, 0x1b, 0x20, 0xa9, 0xde, 0x38, - 0x20, 0xd9, 0xea, 0x20, 0xd9, 0xe9, 0x08, 0x68, - - 0x4a, 0x4a, 0x4a, 0x4a, 0x4d, 0x8f, 0x02, 0x29, - 0x08, 0xa8, 0xa2, 0x03, 0x20, 0x68, 0xf1, 0xf0, - - 0x1d, 0x98, 0xd0, 0x14, 0xa9, 0x8d, 0x20, 0x35, - 0xf1, 0xa2, 0xd2, 0xa0, 0xea, 0xce, 0x67, 0x02, - - 0x20, 0xf7, 0xff, 0xee, 0x67, 0x02, 0xd0, 0x06, - 0xa9, 0x00, 0xaa, 0x20, 0x37, 0xf1, 0xad, 0x8d, - - 0x02, 0xd0, 0x05, 0xae, 0x8c, 0x02, 0x10, 0x1e, - 0xa2, 0x0f, 0xbd, 0xa1, 0x02, 0x2a, 0x30, 0x16, - - 0xca, 0x10, 0xf7, 0xa9, 0x00, 0x2c, 0x7a, 0x02, - 0x30, 0x2e, 0x00, 0xf9, 0x4c, 0x61, 0x6e, 0x67, - - 0x75, 0x61, 0x67, 0x65, 0x3f, 0x00, 0x18, 0x08, - 0x8e, 0x8c, 0x02, 0x20, 0x16, 0xdc, 0xa9, 0x80, - - 0xa0, 0x08, 0x20, 0xab, 0xde, 0x84, 0xfd, 0x20, - 0xe7, 0xff, 0x20, 0xe7, 0xff, 0x28, 0xa9, 0x01, - - 0x2c, 0x7a, 0x02, 0x30, 0x03, 0x4c, 0x00, 0x80, - 0x4c, 0x00, 0x04, 0xa6, 0xf4, 0x84, 0xf4, 0x8c, - - 0x30, 0xfe, 0xa0, 0x00, 0xb1, 0xf6, 0x86, 0xf4, - 0x8e, 0x30, 0xfe, 0x60, 0x85, 0xfc, 0x68, 0x48, - - 0x29, 0x10, 0xd0, 0x03, 0x6c, 0x04, 0x02, 0x8a, - 0x48, 0xba, 0xbd, 0x03, 0x01, 0xd8, 0x38, 0xe9, - - 0x01, 0x85, 0xfd, 0xbd, 0x04, 0x01, 0xe9, 0x00, - 0x85, 0xfe, 0xa5, 0xf4, 0x8d, 0x4a, 0x02, 0x86, - - 0xf0, 0xa2, 0x06, 0x20, 0x68, 0xf1, 0xae, 0x8c, - 0x02, 0x20, 0x16, 0xdc, 0x68, 0xaa, 0xa5, 0xfc, - - 0x58, 0x6c, 0x02, 0x02, 0xa0, 0x00, 0x20, 0xb1, - 0xde, 0xad, 0x67, 0x02, 0x6a, 0xb0, 0xfe, 0x20, - - 0xe7, 0xff, 0x20, 0xe7, 0xff, 0x4c, 0xb8, 0xdb, - 0x38, 0x6e, 0x4f, 0x02, 0x2c, 0x50, 0x02, 0x10, - - 0x07, 0x20, 0x41, 0xe7, 0xa2, 0x00, 0xb0, 0x02, - 0xa2, 0x40, 0x4c, 0x7a, 0xe1, 0xac, 0x09, 0xfe, - - 0x29, 0x3a, 0xd0, 0x34, 0xae, 0x5c, 0x02, 0xd0, - 0x09, 0xe8, 0x20, 0xf3, 0xe4, 0x20, 0x41, 0xe7, - - 0x90, 0xe6, 0x60, 0xd8, 0xa5, 0xfc, 0x48, 0x8a, - 0x48, 0x98, 0x48, 0xa9, 0xde, 0x48, 0xa9, 0x81, - - 0x48, 0xb8, 0xad, 0x08, 0xfe, 0x70, 0x02, 0x10, - 0x5d, 0xa6, 0xea, 0xca, 0x30, 0x30, 0x70, 0x2d, - - 0x4c, 0x88, 0xf5, 0xac, 0x09, 0xfe, 0x2a, 0x0a, - 0xaa, 0x98, 0xa0, 0x07, 0x4c, 0x94, 0xe4, 0xa2, - - 0x02, 0x20, 0x60, 0xe4, 0x90, 0x10, 0xad, 0x85, - 0x02, 0xc9, 0x02, 0xd0, 0x9b, 0xe8, 0x20, 0x60, - - 0xe4, 0x6e, 0xd2, 0x02, 0x30, 0x92, 0x8d, 0x09, - 0xfe, 0xa9, 0xe7, 0x85, 0xea, 0x60, 0x2d, 0x78, - - 0x02, 0x4a, 0x90, 0x07, 0x70, 0x05, 0xac, 0x50, - 0x02, 0x30, 0x92, 0x4a, 0x6a, 0xb0, 0xc4, 0x30, - - 0xce, 0x70, 0xea, 0xa2, 0x05, 0x20, 0x68, 0xf1, - 0xf0, 0xe3, 0x68, 0x68, 0x68, 0xa8, 0x68, 0xaa, - - 0x68, 0x85, 0xfc, 0x6c, 0x06, 0x02, 0xad, 0x4d, - 0xfe, 0x10, 0x3c, 0x2d, 0x79, 0x02, 0x2d, 0x4e, - - 0xfe, 0x6a, 0x6a, 0x90, 0x54, 0xce, 0x40, 0x02, - 0xa5, 0xea, 0x10, 0x02, 0xe6, 0xea, 0xad, 0x51, - - 0x02, 0xf0, 0x1a, 0xce, 0x51, 0x02, 0xd0, 0x15, - 0xae, 0x52, 0x02, 0xad, 0x48, 0x02, 0x4a, 0x90, - - 0x03, 0xae, 0x53, 0x02, 0x2a, 0x49, 0x01, 0x20, - 0x00, 0xea, 0x8e, 0x51, 0x02, 0xa0, 0x04, 0x20, - - 0x94, 0xe4, 0xa9, 0x02, 0x4c, 0x6e, 0xde, 0xad, - 0x6d, 0xfe, 0x10, 0xa7, 0x2d, 0x77, 0x02, 0x2d, - - 0x6e, 0xfe, 0x6a, 0x6a, 0x90, 0x9d, 0xac, 0x85, - 0x02, 0x88, 0xd0, 0x97, 0xa9, 0x02, 0x8d, 0x6d, - - 0xfe, 0x8d, 0x6e, 0xfe, 0xa2, 0x03, 0x4c, 0x3a, - 0xe1, 0x2a, 0x2a, 0x2a, 0x2a, 0x10, 0x5b, 0xa9, - - 0x20, 0xa2, 0x00, 0x8d, 0x4d, 0xfe, 0x8e, 0x49, - 0xfe, 0xa2, 0x08, 0x86, 0xfb, 0x20, 0x5b, 0xe4, - - 0x6e, 0xd7, 0x02, 0x30, 0x44, 0xa8, 0xf0, 0x05, - 0x20, 0x6d, 0xee, 0x30, 0x3c, 0x20, 0x60, 0xe4, - - 0x85, 0xf5, 0x20, 0x60, 0xe4, 0x85, 0xf7, 0x20, - 0x60, 0xe4, 0x85, 0xf6, 0xa4, 0xf5, 0xf0, 0x1b, - - 0x10, 0x16, 0x24, 0xf5, 0x70, 0x05, 0x20, 0xbb, - 0xee, 0x50, 0x07, 0x06, 0xf6, 0x26, 0xf7, 0x20, - - 0x3b, 0xee, 0xac, 0x61, 0x02, 0x4c, 0x7f, 0xee, - 0x20, 0x7f, 0xee, 0xa4, 0xf6, 0x20, 0x7f, 0xee, - - 0xa4, 0xf7, 0x20, 0x7f, 0xee, 0x46, 0xfb, 0xd0, - 0xb4, 0x60, 0x90, 0x7b, 0xa9, 0x40, 0x8d, 0x4d, - - 0xfe, 0xad, 0x83, 0x02, 0xaa, 0x49, 0x0f, 0x48, - 0xa8, 0xbd, 0x91, 0x02, 0x69, 0x00, 0x99, 0x91, - - 0x02, 0xca, 0xf0, 0x03, 0x88, 0xd0, 0xf2, 0x68, - 0x8d, 0x83, 0x02, 0xa2, 0x05, 0xfe, 0x9b, 0x02, - - 0xd0, 0x08, 0xca, 0xd0, 0xf8, 0xa0, 0x05, 0x20, - 0x94, 0xe4, 0xad, 0xb1, 0x02, 0xd0, 0x08, 0xad, - - 0xb2, 0x02, 0xf0, 0x06, 0xce, 0xb2, 0x02, 0xce, - 0xb1, 0x02, 0x2c, 0xce, 0x02, 0x10, 0x0b, 0xee, - - 0xce, 0x02, 0x58, 0x20, 0x47, 0xeb, 0x78, 0xce, - 0xce, 0x02, 0x2c, 0xd7, 0x02, 0x30, 0x0c, 0x20, - - 0x6d, 0xee, 0x49, 0xa0, 0xc9, 0x60, 0x90, 0x03, - 0x20, 0x79, 0xdd, 0x2c, 0xb7, 0xd9, 0x20, 0xa2, - - 0xdc, 0xa5, 0xec, 0x05, 0xed, 0x2d, 0x42, 0x02, - 0xf0, 0x04, 0x38, 0x20, 0x65, 0xf0, 0x20, 0x9b, - - 0xe1, 0x2c, 0xc0, 0xfe, 0x70, 0x04, 0x60, 0x2a, - 0x10, 0x28, 0xae, 0x4c, 0x02, 0xf0, 0x1d, 0xad, - - 0xc2, 0xfe, 0x9d, 0xb5, 0x02, 0xad, 0xc1, 0xfe, - 0x9d, 0xb9, 0x02, 0x8e, 0xbe, 0x02, 0xa0, 0x03, - - 0x20, 0x94, 0xe4, 0xca, 0xd0, 0x03, 0xae, 0x4d, - 0x02, 0x20, 0x8f, 0xde, 0xa9, 0x10, 0x8d, 0x4d, - - 0xfe, 0x60, 0x2a, 0x2a, 0x2a, 0x2a, 0x10, 0x07, - 0x20, 0x65, 0xf0, 0xa9, 0x01, 0xd0, 0xef, 0x4c, - - 0xf3, 0xdc, 0x68, 0xa8, 0x68, 0xaa, 0x68, 0x85, - 0xfc, 0xa5, 0xfc, 0x40, 0x8c, 0xbe, 0x02, 0xe0, - - 0x05, 0x90, 0x02, 0xa2, 0x04, 0x8e, 0x4c, 0x02, - 0xac, 0x4e, 0x02, 0x88, 0x98, 0x29, 0x08, 0x18, - - 0x6d, 0x4c, 0x02, 0xe9, 0x00, 0x8d, 0xc0, 0xfe, - 0x60, 0xa9, 0xc3, 0x85, 0xfe, 0xa9, 0x00, 0x85, - - 0xfd, 0xc8, 0xb1, 0xfd, 0x20, 0xe3, 0xff, 0xaa, - 0xd0, 0xf7, 0x60, 0x8e, 0xb1, 0x02, 0x8c, 0xb2, - - 0x02, 0xa9, 0xff, 0xd0, 0x02, 0xa9, 0x00, 0x85, - 0xe6, 0x8a, 0x48, 0x98, 0x48, 0xac, 0x56, 0x02, - - 0xf0, 0x14, 0x38, 0x66, 0xeb, 0x20, 0xd7, 0xff, - 0x08, 0x46, 0xeb, 0x28, 0x90, 0x25, 0xa9, 0x00, - - 0x8d, 0x56, 0x02, 0x20, 0xce, 0xff, 0x24, 0xff, - 0x30, 0x16, 0xae, 0x41, 0x02, 0x20, 0x77, 0xe5, - - 0x90, 0x11, 0x24, 0xe6, 0x50, 0xf0, 0xad, 0xb1, - 0x02, 0x0d, 0xb2, 0x02, 0xd0, 0xe8, 0xb0, 0x05, - - 0x38, 0xa9, 0x1b, 0x85, 0xe6, 0x68, 0xa8, 0x68, - 0xaa, 0xa5, 0xe6, 0x60, 0x29, 0x43, 0x28, 0x00, - - 0x2e, 0xe0, 0x31, 0x05, 0x46, 0x58, 0xe3, 0x42, - 0xff, 0x42, 0x41, 0x53, 0x49, 0x43, 0xe0, 0x18, - - 0x00, 0x43, 0x41, 0x54, 0xe0, 0x31, 0x05, 0x43, - 0x4f, 0x44, 0x45, 0xe3, 0x48, 0x88, 0x45, 0x58, - - 0x45, 0x43, 0xf6, 0x8d, 0x00, 0x48, 0x45, 0x4c, - 0x50, 0xf0, 0xb9, 0xff, 0x4b, 0x45, 0x59, 0xe3, - - 0x27, 0xff, 0x4c, 0x4f, 0x41, 0x44, 0xe2, 0x3c, - 0x00, 0x4c, 0x49, 0x4e, 0x45, 0xe6, 0x59, 0x01, - - 0x4d, 0x4f, 0x54, 0x4f, 0x52, 0xe3, 0x48, 0x89, - 0x4f, 0x50, 0x54, 0xe3, 0x48, 0x8b, 0x52, 0x55, - - 0x4e, 0xe0, 0x31, 0x04, 0x52, 0x4f, 0x4d, 0xe3, - 0x48, 0x8d, 0x53, 0x41, 0x56, 0x45, 0xe2, 0x3e, - - 0x00, 0x53, 0x50, 0x4f, 0x4f, 0x4c, 0xe2, 0x81, - 0x00, 0x54, 0x41, 0x50, 0x45, 0xe3, 0x48, 0x8c, - - 0x54, 0x56, 0xe3, 0x48, 0x90, 0xe0, 0x31, 0x03, - 0x00, 0x86, 0xf2, 0x84, 0xf3, 0xa9, 0x08, 0x20, - - 0x31, 0xe0, 0xa0, 0x00, 0xb1, 0xf2, 0xc9, 0x0d, - 0xf0, 0x04, 0xc8, 0xd0, 0xf7, 0x60, 0xa0, 0xff, - - 0x20, 0x39, 0xe0, 0xf0, 0x72, 0xc9, 0x2a, 0xf0, - 0xf7, 0x20, 0x3a, 0xe0, 0xf0, 0x69, 0xc9, 0x7c, - - 0xf0, 0x65, 0xc9, 0x2f, 0xd0, 0x08, 0xc8, 0x20, - 0x09, 0xe0, 0xa9, 0x02, 0xd0, 0x73, 0x84, 0xe6, - - 0xa2, 0x00, 0xf0, 0x13, 0x5d, 0x10, 0xdf, 0x29, - 0xdf, 0xd0, 0x17, 0xc8, 0x18, 0xb0, 0x25, 0xe8, - - 0xb1, 0xf2, 0x20, 0xe3, 0xe4, 0x90, 0xed, 0xbd, - 0x10, 0xdf, 0x30, 0x16, 0xb1, 0xf2, 0xc9, 0x2e, - - 0xf0, 0x04, 0x18, 0xa4, 0xe6, 0x88, 0xc8, 0xe8, - 0xe8, 0xbd, 0x0e, 0xdf, 0xf0, 0x33, 0x10, 0xf8, - - 0x30, 0xdb, 0xe8, 0xe8, 0xca, 0xca, 0x48, 0xbd, - 0x11, 0xdf, 0x48, 0x20, 0x3a, 0xe0, 0x18, 0x08, - - 0x20, 0x04, 0xe0, 0x40, 0xbd, 0x12, 0xdf, 0x30, - 0x0e, 0x98, 0xbc, 0x12, 0xdf, 0x18, 0x65, 0xf2, - - 0xaa, 0x98, 0xa4, 0xf3, 0x90, 0x01, 0xc8, 0x60, - 0xae, 0x4b, 0x02, 0x30, 0x04, 0x38, 0x4c, 0xe7, - - 0xdb, 0xa4, 0xe6, 0xa2, 0x04, 0x20, 0x68, 0xf1, - 0xf0, 0xed, 0xa5, 0xe6, 0x20, 0x0d, 0xe0, 0xa9, - - 0x03, 0x6c, 0x1e, 0x02, 0x0a, 0x29, 0x01, 0x10, - 0xf8, 0xc8, 0xb1, 0xf2, 0xc9, 0x20, 0xf0, 0xf9, - - 0xc9, 0x0d, 0x60, 0x90, 0xf5, 0x20, 0x3a, 0xe0, - 0xc9, 0x2c, 0xd0, 0xf4, 0xc8, 0x60, 0x20, 0x3a, - - 0xe0, 0x20, 0x7d, 0xe0, 0x90, 0x37, 0x85, 0xe6, - 0x20, 0x7c, 0xe0, 0x90, 0x19, 0xaa, 0xa5, 0xe6, - - 0x0a, 0xb0, 0x2a, 0x0a, 0xb0, 0x27, 0x65, 0xe6, - 0xb0, 0x23, 0x0a, 0xb0, 0x20, 0x85, 0xe6, 0x8a, - - 0x65, 0xe6, 0xb0, 0x19, 0x90, 0xe0, 0xa6, 0xe6, - 0xc9, 0x0d, 0x38, 0x60, 0xc8, 0xb1, 0xf2, 0xc9, - - 0x3a, 0xb0, 0x0a, 0xc9, 0x30, 0x90, 0x06, 0x29, - 0x0f, 0x60, 0x20, 0x45, 0xe0, 0x18, 0x60, 0x20, - - 0x7d, 0xe0, 0xb0, 0x0e, 0x29, 0xdf, 0xc9, 0x47, - 0xb0, 0xf0, 0xc9, 0x41, 0x90, 0xec, 0x08, 0xe9, - - 0x37, 0x28, 0xc8, 0x60, 0x48, 0x8a, 0x48, 0x98, - 0x48, 0xba, 0xbd, 0x03, 0x01, 0x48, 0x2c, 0x60, - - 0x02, 0x10, 0x08, 0xa8, 0xa9, 0x04, 0x20, 0x7e, - 0xe5, 0xb0, 0x52, 0x18, 0xa9, 0x02, 0x2c, 0x7c, - - 0x02, 0xd0, 0x05, 0x68, 0x48, 0x20, 0xc0, 0xc4, - 0xa9, 0x08, 0x2c, 0x7c, 0x02, 0xd0, 0x02, 0x90, - - 0x05, 0x68, 0x48, 0x20, 0x14, 0xe1, 0xad, 0x7c, - 0x02, 0x6a, 0x90, 0x1b, 0xa4, 0xea, 0x88, 0x10, - - 0x16, 0x68, 0x48, 0x08, 0x78, 0xa2, 0x02, 0x48, - 0x20, 0x5b, 0xe4, 0x90, 0x03, 0x20, 0x70, 0xe1, - - 0x68, 0xa2, 0x02, 0x20, 0xf8, 0xe1, 0x28, 0xa9, - 0x10, 0x2c, 0x7c, 0x02, 0xd0, 0x0f, 0xac, 0x57, - - 0x02, 0xf0, 0x0a, 0x68, 0x48, 0x38, 0x66, 0xeb, - 0x20, 0xd4, 0xff, 0x46, 0xeb, 0x68, 0x68, 0xa8, - - 0x68, 0xaa, 0x68, 0x60, 0x2c, 0x7c, 0x02, 0x70, - 0x20, 0xcd, 0x86, 0x02, 0xf0, 0x1b, 0x08, 0x78, - - 0xaa, 0xa9, 0x04, 0x2c, 0x7c, 0x02, 0xd0, 0x10, - 0x8a, 0xa2, 0x03, 0x20, 0xf8, 0xe1, 0xb0, 0x08, - - 0x2c, 0xd2, 0x02, 0x10, 0x03, 0x20, 0x3a, 0xe1, - 0x28, 0x60, 0xad, 0x85, 0x02, 0xf0, 0x6e, 0xc9, - - 0x01, 0xd0, 0x21, 0x20, 0x60, 0xe4, 0x6e, 0xd2, - 0x02, 0x30, 0x45, 0xa0, 0x82, 0x8c, 0x6e, 0xfe, - - 0x8d, 0x61, 0xfe, 0xad, 0x6c, 0xfe, 0x29, 0xf1, - 0x09, 0x0c, 0x8d, 0x6c, 0xfe, 0x09, 0x0e, 0x8d, - - 0x6c, 0xfe, 0xd0, 0x2c, 0xc9, 0x02, 0xd0, 0x29, - 0xa4, 0xea, 0x88, 0x10, 0x40, 0x4e, 0xd2, 0x02, - - 0x4e, 0x4f, 0x02, 0x20, 0x41, 0xe7, 0x90, 0x18, - 0xa2, 0x20, 0xa0, 0x9f, 0x08, 0x78, 0x98, 0x86, - - 0xfa, 0x2d, 0x50, 0x02, 0x45, 0xfa, 0xae, 0x50, - 0x02, 0x8d, 0x50, 0x02, 0x8d, 0x08, 0xfe, 0x28, - - 0x60, 0x18, 0xa9, 0x01, 0x20, 0xa2, 0xe1, 0x6e, - 0xd2, 0x02, 0x60, 0x2c, 0xd2, 0x02, 0x30, 0xfa, - - 0xa9, 0x00, 0xa2, 0x03, 0xac, 0x85, 0x02, 0x20, - 0x7e, 0xe5, 0x6c, 0x22, 0x02, 0x18, 0x48, 0x08, - - 0x78, 0xb0, 0x08, 0xbd, 0xad, 0xe9, 0x10, 0x03, - 0x20, 0xa2, 0xec, 0x38, 0x7e, 0xcf, 0x02, 0xe0, - - 0x02, 0xb0, 0x08, 0xa9, 0x00, 0x8d, 0x68, 0x02, - 0x8d, 0x6a, 0x02, 0x20, 0x3b, 0xe7, 0x28, 0x68, - - 0x60, 0x50, 0x07, 0xbd, 0xd8, 0x02, 0x9d, 0xe1, - 0x02, 0x60, 0x08, 0x78, 0x08, 0x38, 0xbd, 0xe1, - - 0x02, 0xfd, 0xd8, 0x02, 0xb0, 0x04, 0x38, 0xfd, - 0x47, 0xe4, 0x28, 0x90, 0x06, 0x18, 0x7d, 0x47, - - 0xe4, 0x49, 0xff, 0xa0, 0x00, 0xaa, 0x28, 0x60, - 0x78, 0x20, 0xb0, 0xe4, 0x90, 0x0f, 0x20, 0xea, - - 0xe9, 0x08, 0x48, 0x20, 0xeb, 0xee, 0x68, 0x28, - 0x30, 0x03, 0x58, 0xb0, 0xeb, 0x60, 0x48, 0xa9, - - 0x00, 0x9d, 0xee, 0x02, 0x9d, 0xef, 0x02, 0x9d, - 0xf0, 0x02, 0x9d, 0xf1, 0x02, 0x68, 0x60, 0x84, - - 0xe6, 0x2a, 0x2a, 0x2a, 0x2a, 0xa0, 0x04, 0x2a, - 0x3e, 0xee, 0x02, 0x3e, 0xef, 0x02, 0x3e, 0xf0, - - 0x02, 0x3e, 0xf1, 0x02, 0xb0, 0x31, 0x88, 0xd0, - 0xee, 0xa4, 0xe6, 0x60, 0xa9, 0xff, 0x86, 0xf2, - - 0x84, 0xf3, 0x8e, 0xee, 0x02, 0x8c, 0xef, 0x02, - 0x48, 0xa2, 0x02, 0x20, 0x0e, 0xe2, 0xa0, 0xff, - - 0x8c, 0xf4, 0x02, 0xc8, 0x20, 0x1d, 0xea, 0x20, - 0x2f, 0xea, 0x90, 0xfb, 0x68, 0x48, 0xf0, 0x62, - - 0x20, 0xad, 0xe2, 0xb0, 0x3b, 0xf0, 0x3e, 0x00, - 0xfc, 0x42, 0x61, 0x64, 0x20, 0x61, 0x64, 0x64, - - 0x72, 0x65, 0x73, 0x73, 0x00, 0xa2, 0x10, 0x20, - 0x68, 0xf1, 0xf0, 0x23, 0x20, 0x8b, 0xf6, 0xa9, - - 0x00, 0x08, 0x84, 0xe6, 0xac, 0x57, 0x02, 0x8d, - 0x57, 0x02, 0xf0, 0x03, 0x20, 0xce, 0xff, 0xa4, - - 0xe6, 0x28, 0xf0, 0x0b, 0xa9, 0x80, 0x20, 0xce, - 0xff, 0xa8, 0xf0, 0x74, 0x8d, 0x57, 0x02, 0x60, - - 0xd0, 0x6e, 0xee, 0xf4, 0x02, 0xa2, 0xee, 0xa0, - 0x02, 0x68, 0x4c, 0xdd, 0xff, 0x20, 0x3a, 0xe0, - - 0x20, 0x8f, 0xe0, 0x90, 0x0c, 0x20, 0x0e, 0xe2, - 0x20, 0x1f, 0xe2, 0x20, 0x8f, 0xe0, 0xb0, 0xf8, - - 0x38, 0x60, 0xa2, 0x0a, 0x20, 0xad, 0xe2, 0x90, - 0x47, 0xb8, 0xb1, 0xf2, 0xc9, 0x2b, 0xd0, 0x04, - - 0x2c, 0xb7, 0xd9, 0xc8, 0xa2, 0x0e, 0x20, 0xad, - 0xe2, 0x90, 0x35, 0x08, 0x50, 0x0f, 0xa2, 0xfc, - - 0x18, 0xbd, 0xfc, 0x01, 0x7d, 0x00, 0x02, 0x9d, - 0x00, 0x02, 0xe8, 0xd0, 0xf4, 0xa2, 0x03, 0xbd, - - 0xf8, 0x02, 0x9d, 0xf4, 0x02, 0x9d, 0xf0, 0x02, - 0xca, 0x10, 0xf4, 0x28, 0xf0, 0xa7, 0xa2, 0x06, - - 0x20, 0xad, 0xe2, 0x90, 0x0b, 0xf0, 0x9e, 0xa2, - 0x02, 0x20, 0xad, 0xe2, 0x90, 0x02, 0xf0, 0x95, - - 0x00, 0xfe, 0x42, 0x61, 0x64, 0x20, 0x63, 0x6f, - 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x00, 0xfb, 0x42, - - 0x61, 0x64, 0x20, 0x6b, 0x65, 0x79, 0x00, 0x20, - 0x4e, 0xe0, 0x90, 0xf1, 0xe0, 0x10, 0xb0, 0xed, - - 0x20, 0x45, 0xe0, 0x08, 0xae, 0x10, 0x0b, 0x98, - 0x48, 0x20, 0xd1, 0xe3, 0x68, 0xa8, 0x28, 0xd0, - - 0x36, 0x60, 0x20, 0x4e, 0xe0, 0x90, 0xc9, 0x8a, - 0x48, 0xa9, 0x00, 0x85, 0xe5, 0x85, 0xe4, 0x20, - - 0x43, 0xe0, 0xf0, 0x18, 0x20, 0x4e, 0xe0, 0x90, - 0xb7, 0x86, 0xe5, 0x20, 0x45, 0xe0, 0xf0, 0x0c, - - 0x20, 0x4e, 0xe0, 0x90, 0xab, 0x86, 0xe4, 0x20, - 0x3a, 0xe0, 0xd0, 0xa4, 0xa4, 0xe4, 0xa6, 0xe5, - - 0x68, 0x20, 0xf4, 0xff, 0x70, 0x9a, 0x60, 0x38, - 0x20, 0x1e, 0xea, 0x20, 0x2f, 0xea, 0xb0, 0x08, - - 0xe8, 0xf0, 0x9a, 0x9d, 0x00, 0x0b, 0x90, 0xf3, - 0xd0, 0x93, 0x08, 0x78, 0x20, 0xd1, 0xe3, 0xa2, - - 0x10, 0xe4, 0xe6, 0xf0, 0x0e, 0xbd, 0x00, 0x0b, - 0xd9, 0x00, 0x0b, 0xd0, 0x06, 0xad, 0x10, 0x0b, - - 0x9d, 0x00, 0x0b, 0xca, 0x10, 0xeb, 0x28, 0x60, - 0x08, 0x78, 0xad, 0x10, 0x0b, 0x38, 0xf9, 0x00, - - 0x0b, 0x85, 0xfb, 0x8a, 0x48, 0xa2, 0x10, 0xbd, - 0x00, 0x0b, 0x38, 0xf9, 0x00, 0x0b, 0x90, 0x08, - - 0xf0, 0x06, 0xc5, 0xfb, 0xb0, 0x02, 0x85, 0xfb, - 0xca, 0x10, 0xec, 0x68, 0xaa, 0xa5, 0xfb, 0x28, - - 0x60, 0x08, 0x78, 0x8a, 0x48, 0xa4, 0xe6, 0x20, - 0xa8, 0xe3, 0xb9, 0x00, 0x0b, 0xa8, 0x18, 0x65, - - 0xfb, 0xaa, 0x85, 0xfa, 0xad, 0x68, 0x02, 0xf0, - 0x0d, 0x00, 0xfa, 0x4b, 0x65, 0x79, 0x20, 0x69, - - 0x6e, 0x20, 0x75, 0x73, 0x65, 0x00, 0xce, 0x84, - 0x02, 0x68, 0x38, 0xe5, 0xfa, 0x85, 0xfa, 0xf0, - - 0x0c, 0xbd, 0x01, 0x0b, 0x99, 0x01, 0x0b, 0xc8, - 0xe8, 0xc6, 0xfa, 0xd0, 0xf4, 0x98, 0x48, 0xa4, - - 0xe6, 0xa2, 0x10, 0xbd, 0x00, 0x0b, 0xd9, 0x00, - 0x0b, 0x90, 0x07, 0xf0, 0x05, 0xe5, 0xfb, 0x9d, - - 0x00, 0x0b, 0xca, 0x10, 0xee, 0xad, 0x10, 0x0b, - 0x99, 0x00, 0x0b, 0x68, 0x8d, 0x10, 0x0b, 0xaa, - - 0xee, 0x84, 0x02, 0x28, 0x60, 0x03, 0x0a, 0x08, - 0x07, 0x07, 0x07, 0x07, 0x07, 0x09, 0x00, 0x00, - - 0xc0, 0xc0, 0x50, 0x60, 0x70, 0x80, 0x00, 0xe0, - 0x00, 0x40, 0xc0, 0xf0, 0xf0, 0xf0, 0xf0, 0xc0, - - 0xbd, 0x3e, 0xe4, 0x85, 0xfa, 0xbd, 0x35, 0xe4, - 0x85, 0xfb, 0x60, 0x2c, 0xb7, 0xd9, 0x70, 0x01, - - 0xb8, 0x6c, 0x2c, 0x02, 0x08, 0x78, 0xbd, 0xd8, - 0x02, 0xdd, 0xe1, 0x02, 0xf0, 0x72, 0xa8, 0x20, - - 0x50, 0xe4, 0xb1, 0xfa, 0x70, 0x1b, 0x48, 0xc8, - 0x98, 0xd0, 0x03, 0xbd, 0x47, 0xe4, 0x9d, 0xd8, - - 0x02, 0xe0, 0x02, 0x90, 0x0a, 0xdd, 0xe1, 0x02, - 0xd0, 0x05, 0xa0, 0x00, 0x20, 0x94, 0xe4, 0x68, - - 0xa8, 0x28, 0x18, 0x60, 0x08, 0x78, 0x48, 0x85, - 0xfa, 0xb9, 0xbf, 0x02, 0xf0, 0x41, 0x98, 0xa4, - - 0xfa, 0x20, 0xa5, 0xf0, 0x68, 0x28, 0x18, 0x60, - 0x98, 0xa0, 0x02, 0x20, 0x94, 0xe4, 0xa8, 0x98, - - 0x6c, 0x2a, 0x02, 0x08, 0x78, 0x48, 0xbc, 0xe1, - 0x02, 0xc8, 0xd0, 0x03, 0xbc, 0x47, 0xe4, 0x98, - - 0xdd, 0xd8, 0x02, 0xf0, 0x0f, 0xbc, 0xe1, 0x02, - 0x9d, 0xe1, 0x02, 0x20, 0x50, 0xe4, 0x68, 0x91, - - 0xfa, 0x28, 0x18, 0x60, 0x68, 0xe0, 0x02, 0xb0, - 0x07, 0xa0, 0x01, 0x20, 0x94, 0xe4, 0x48, 0x68, - - 0x28, 0x38, 0x60, 0x48, 0x29, 0xdf, 0xc9, 0x41, - 0x90, 0x04, 0xc9, 0x5b, 0x90, 0x01, 0x38, 0x68, - - 0x60, 0xa2, 0x00, 0x8a, 0x2d, 0x45, 0x02, 0xd0, - 0xb6, 0x98, 0x4d, 0x6c, 0x02, 0x0d, 0x75, 0x02, - - 0xd0, 0xa6, 0xad, 0x58, 0x02, 0x6a, 0x98, 0xb0, - 0x0a, 0xa0, 0x06, 0x20, 0x94, 0xe4, 0x90, 0x03, - - 0x20, 0x74, 0xe6, 0x18, 0x60, 0x6a, 0x68, 0xb0, - 0x79, 0x98, 0x48, 0x4a, 0x4a, 0x4a, 0x4a, 0x49, - - 0x04, 0xa8, 0xb9, 0x65, 0x02, 0xc9, 0x01, 0xf0, - 0x6b, 0x68, 0x90, 0x0d, 0x29, 0x0f, 0x18, 0x79, - - 0x65, 0x02, 0x18, 0x60, 0x20, 0x6f, 0xe8, 0x68, - 0xaa, 0x20, 0x60, 0xe4, 0xb0, 0x55, 0x48, 0xe0, - - 0x01, 0xd0, 0x06, 0x20, 0x73, 0xe1, 0xa2, 0x01, - 0x38, 0x68, 0x90, 0x05, 0xac, 0x45, 0x02, 0xd0, - - 0x41, 0xa8, 0x10, 0x3e, 0x29, 0x0f, 0xc9, 0x0b, - 0x90, 0xbf, 0x69, 0x7b, 0x48, 0xad, 0x7d, 0x02, - - 0xd0, 0xb3, 0xad, 0x7c, 0x02, 0x6a, 0x6a, 0x68, - 0xb0, 0xcf, 0xc9, 0x87, 0xf0, 0x38, 0xa8, 0x8a, - - 0x48, 0x98, 0x20, 0xce, 0xd8, 0x68, 0xaa, 0x2c, - 0x5f, 0x02, 0x10, 0x05, 0xa9, 0x06, 0x6c, 0x24, - - 0x02, 0xad, 0x68, 0x02, 0xf0, 0xb3, 0xac, 0xc9, - 0x02, 0xb9, 0x01, 0x0b, 0xee, 0xc9, 0x02, 0xce, - - 0x68, 0x02, 0x18, 0x60, 0x68, 0x29, 0x0f, 0xa8, - 0x20, 0xa8, 0xe3, 0x8d, 0x68, 0x02, 0xb9, 0x00, - - 0x0b, 0x8d, 0xc9, 0x02, 0xd0, 0xd1, 0x8a, 0x48, - 0x20, 0x05, 0xd9, 0xa8, 0xf0, 0x86, 0x68, 0xaa, - - 0x98, 0x18, 0x60, 0x21, 0xe8, 0x88, 0xe9, 0xd3, - 0xe6, 0x97, 0xe9, 0x97, 0xe9, 0x76, 0xe9, 0x88, - - 0xe9, 0x8b, 0xe6, 0x89, 0xe6, 0xb0, 0xe6, 0xb2, - 0xe6, 0x95, 0xe9, 0x8c, 0xe9, 0xf9, 0xe6, 0xfa, - - 0xe6, 0xa8, 0xf0, 0x06, 0xe7, 0x8c, 0xde, 0xc8, - 0xe9, 0xb6, 0xe9, 0x07, 0xcd, 0xb4, 0xf0, 0x6c, - - 0xe8, 0xd9, 0xe9, 0x75, 0xe2, 0x45, 0xf0, 0xcf, - 0xf0, 0xcd, 0xf0, 0x97, 0xe1, 0x73, 0xe6, 0x74, - - 0xe6, 0x5c, 0xe6, 0x35, 0xe0, 0x4f, 0xe7, 0x13, - 0xe7, 0x29, 0xe7, 0x85, 0xf0, 0x23, 0xd9, 0x26, - - 0xd9, 0x47, 0xd6, 0xc2, 0xd7, 0x57, 0xe6, 0x7f, - 0xe6, 0xaf, 0xe4, 0x34, 0xe0, 0x35, 0xf1, 0x35, - - 0xf1, 0xe7, 0xdb, 0x68, 0xf1, 0xe3, 0xea, 0x60, - 0xe4, 0xaa, 0xff, 0xf4, 0xea, 0xae, 0xff, 0xf9, - - 0xea, 0xb2, 0xff, 0xfe, 0xea, 0x5b, 0xe4, 0xf3, - 0xe4, 0xff, 0xe9, 0x10, 0xea, 0x7c, 0xe1, 0xa7, - - 0xff, 0x6d, 0xee, 0x7f, 0xee, 0xc0, 0xe9, 0x9c, - 0xe9, 0x59, 0xe6, 0x02, 0xe9, 0xd5, 0xe8, 0xe8, - - 0xe8, 0xd1, 0xe8, 0xe4, 0xe8, 0x03, 0xe8, 0x0b, - 0xe8, 0x2d, 0xe8, 0xae, 0xe8, 0x35, 0xc7, 0xf3, - - 0xcb, 0x48, 0xc7, 0xe0, 0xc8, 0xce, 0xd5, 0xa9, - 0x00, 0x6c, 0x00, 0x02, 0xa2, 0x00, 0x24, 0xff, - - 0x10, 0x11, 0xad, 0x76, 0x02, 0xd0, 0x0a, 0x58, - 0x8d, 0x69, 0x02, 0x20, 0x8d, 0xf6, 0x20, 0xaa, - - 0xf0, 0xa2, 0xff, 0x18, 0x66, 0xff, 0x2c, 0x7a, - 0x02, 0x30, 0x01, 0x60, 0x4c, 0x03, 0x04, 0xad, - - 0x82, 0x02, 0xa8, 0x2a, 0xe0, 0x01, 0x6a, 0x50, - 0x1e, 0xa9, 0x38, 0x49, 0x3f, 0x85, 0xfa, 0xac, - - 0x82, 0x02, 0xe0, 0x09, 0xb0, 0x17, 0x3d, 0xad, - 0xe9, 0x85, 0xfb, 0x98, 0x05, 0xfa, 0x45, 0xfa, - - 0x05, 0xfb, 0x09, 0x40, 0x4d, 0x5d, 0x02, 0x8d, - 0x82, 0x02, 0x8d, 0x10, 0xfe, 0x98, 0xaa, 0x60, - - 0xc8, 0x18, 0xb9, 0x52, 0x02, 0x48, 0x8a, 0x99, - 0x52, 0x02, 0x68, 0xa8, 0xad, 0x51, 0x02, 0xd0, - - 0x10, 0x8e, 0x51, 0x02, 0xad, 0x48, 0x02, 0x08, - 0x6a, 0x28, 0x2a, 0x8d, 0x48, 0x02, 0x8d, 0x20, - - 0xfe, 0x50, 0xda, 0x8a, 0x29, 0x01, 0x48, 0xad, - 0x50, 0x02, 0x2a, 0xe0, 0x01, 0x6a, 0xcd, 0x50, - - 0x02, 0x08, 0x8d, 0x50, 0x02, 0x8d, 0x08, 0xfe, - 0x20, 0x73, 0xe1, 0x28, 0xf0, 0x03, 0x2c, 0x09, - - 0xfe, 0xae, 0x41, 0x02, 0x68, 0x8d, 0x41, 0x02, - 0x60, 0x98, 0xe0, 0x0a, 0xb0, 0xb0, 0xbc, 0xbf, - - 0x02, 0x9d, 0xbf, 0x02, 0x50, 0xa7, 0xf0, 0x03, - 0x20, 0x8c, 0xde, 0xad, 0x4d, 0x02, 0x8e, 0x4d, - - 0x02, 0xaa, 0x60, 0x98, 0x30, 0x0b, 0x58, 0x20, - 0xbb, 0xde, 0xb0, 0x03, 0xaa, 0xa9, 0x00, 0xa8, - - 0x60, 0x8a, 0x49, 0x7f, 0xaa, 0x20, 0x68, 0xf0, - 0x2a, 0xa2, 0xff, 0xa0, 0xff, 0xb0, 0x02, 0xe8, - - 0xc8, 0x60, 0x8a, 0x49, 0xff, 0xaa, 0xe0, 0x02, - 0xb8, 0x50, 0x03, 0x2c, 0xb7, 0xd9, 0x6c, 0x2e, - - 0x02, 0x38, 0xa2, 0x01, 0x20, 0x38, 0xe7, 0xc0, - 0x01, 0xb0, 0x03, 0xec, 0x5b, 0x02, 0x60, 0x30, - - 0xe1, 0xf0, 0x0c, 0xe0, 0x05, 0xb0, 0xd2, 0xbc, - 0xb9, 0x02, 0xbd, 0xb5, 0x02, 0xaa, 0x60, 0xad, - - 0x40, 0xfe, 0x6a, 0x6a, 0x6a, 0x6a, 0x49, 0xff, - 0x29, 0x03, 0xac, 0xbe, 0x02, 0x8e, 0xbe, 0x02, - - 0xaa, 0x60, 0x48, 0x08, 0x78, 0x85, 0xef, 0x86, - 0xf0, 0x84, 0xf1, 0xa2, 0x07, 0xc9, 0x75, 0x90, - - 0x41, 0xc9, 0xa1, 0x90, 0x09, 0xc9, 0xa6, 0x90, - 0x3f, 0x18, 0xa9, 0xa1, 0x69, 0x00, 0x38, 0xe9, - - 0x5f, 0x0a, 0x38, 0x84, 0xf1, 0xa8, 0x2c, 0x5e, - 0x02, 0x10, 0x07, 0x8a, 0xb8, 0x20, 0x7e, 0xe5, - - 0x70, 0x1a, 0xb9, 0xb4, 0xe5, 0x85, 0xfb, 0xb9, - 0xb3, 0xe5, 0x85, 0xfa, 0xa5, 0xef, 0xa4, 0xf1, - - 0xb0, 0x04, 0xa0, 0x00, 0xb1, 0xf0, 0x38, 0xa6, - 0xf0, 0x20, 0x58, 0xf0, 0x6a, 0x28, 0x2a, 0x68, - - 0xb8, 0x60, 0xa0, 0x00, 0xc9, 0x16, 0x90, 0xc9, - 0x08, 0x08, 0x68, 0x68, 0x20, 0x68, 0xf1, 0xd0, - - 0x05, 0xa6, 0xf0, 0x4c, 0xbc, 0xe7, 0x28, 0x68, - 0x2c, 0xb7, 0xd9, 0x60, 0xa5, 0xeb, 0x30, 0x32, - - 0xa9, 0x08, 0x25, 0xe2, 0xd0, 0x04, 0xa9, 0x88, - 0x25, 0xbb, 0x60, 0x48, 0x08, 0x78, 0x85, 0xef, - - 0x86, 0xf0, 0x84, 0xf1, 0xa2, 0x08, 0xc9, 0xe0, - 0xb0, 0x90, 0xc9, 0x0e, 0xb0, 0xca, 0x69, 0x44, - - 0x0a, 0x90, 0x90, 0x20, 0x15, 0xe8, 0xa1, 0xf9, - 0x91, 0xf0, 0x60, 0x20, 0x15, 0xe8, 0xb1, 0xf0, - - 0x81, 0xf9, 0xa9, 0x00, 0x60, 0x85, 0xfa, 0xc8, - 0xb1, 0xf0, 0x85, 0xfb, 0xa0, 0x04, 0xa2, 0x01, - - 0x60, 0xd0, 0xfb, 0x00, 0xf7, 0x4f, 0x53, 0x20, - 0x31, 0x2e, 0x32, 0x30, 0x00, 0xc8, 0xb1, 0xf0, - - 0xc9, 0xff, 0xf0, 0x59, 0xc9, 0x20, 0xa2, 0x08, - 0xb0, 0x90, 0x88, 0x20, 0xc9, 0xe8, 0x09, 0x04, - - 0xaa, 0x90, 0x05, 0x20, 0xae, 0xe1, 0xa0, 0x01, - 0x20, 0xc9, 0xe8, 0x85, 0xfa, 0x08, 0xa0, 0x06, - - 0xb1, 0xf0, 0x48, 0xa0, 0x04, 0xb1, 0xf0, 0x48, - 0xa0, 0x02, 0xb1, 0xf0, 0x2a, 0x38, 0xe9, 0x02, - - 0x0a, 0x0a, 0x05, 0xfa, 0x20, 0xf8, 0xe1, 0x90, - 0x1e, 0x68, 0x68, 0x28, 0xa6, 0xd0, 0x60, 0x08, - - 0x78, 0xad, 0x63, 0x02, 0x29, 0x07, 0x09, 0x04, - 0xaa, 0xad, 0x64, 0x02, 0x20, 0xb0, 0xe4, 0xad, - - 0x66, 0x02, 0x48, 0xad, 0x65, 0x02, 0x48, 0x38, - 0x7e, 0x00, 0x08, 0x30, 0x17, 0x08, 0xc8, 0xb1, - - 0xf0, 0x48, 0xc8, 0xb1, 0xf0, 0x48, 0xa0, 0x00, - 0xb1, 0xf0, 0xa2, 0x08, 0x20, 0xf8, 0xe1, 0xb0, - - 0xc8, 0x6e, 0xd7, 0x02, 0x68, 0x20, 0xb0, 0xe4, - 0x68, 0x20, 0xb0, 0xe4, 0x28, 0x60, 0xe9, 0x01, - - 0x0a, 0x0a, 0x0a, 0x0a, 0x09, 0x0f, 0xaa, 0xa9, - 0x00, 0xa0, 0x10, 0xc0, 0x0e, 0xb0, 0x02, 0xb1, - - 0xf0, 0x9d, 0xc0, 0x08, 0xca, 0x88, 0xd0, 0xf3, - 0x60, 0xb1, 0xf0, 0xc9, 0x10, 0x29, 0x03, 0xc8, - - 0x60, 0xa2, 0x0f, 0xd0, 0x03, 0xae, 0x83, 0x02, - 0xa0, 0x04, 0xbd, 0x8d, 0x02, 0x91, 0xf0, 0xe8, - - 0x88, 0x10, 0xf7, 0x60, 0xa9, 0x0f, 0xd0, 0x06, - 0xad, 0x83, 0x02, 0x49, 0x0f, 0x18, 0x48, 0xaa, - - 0xa0, 0x04, 0xb1, 0xf0, 0x9d, 0x8d, 0x02, 0xe8, - 0x88, 0x10, 0xf7, 0x68, 0xb0, 0xe5, 0x8d, 0x83, - - 0x02, 0x60, 0xa0, 0x04, 0xb1, 0xf0, 0x99, 0xb1, - 0x02, 0x88, 0xc0, 0x02, 0xb0, 0xf6, 0xb1, 0xf0, - - 0x85, 0xe9, 0x88, 0x8c, 0x69, 0x02, 0xb1, 0xf0, - 0x85, 0xe8, 0x58, 0x90, 0x07, 0xa9, 0x07, 0x88, - - 0xc8, 0x20, 0xee, 0xff, 0x20, 0xe0, 0xff, 0xb0, - 0x49, 0xaa, 0xad, 0x7c, 0x02, 0x6a, 0x6a, 0x8a, - - 0xb0, 0x05, 0xae, 0x6a, 0x02, 0xd0, 0xea, 0xc9, - 0x7f, 0xd0, 0x07, 0xc0, 0x00, 0xf0, 0xe5, 0x88, - - 0xb0, 0xdf, 0xc9, 0x15, 0xd0, 0x0d, 0x98, 0xf0, - 0xdb, 0xa9, 0x7f, 0x20, 0xee, 0xff, 0x88, 0xd0, - - 0xfa, 0xf0, 0xd1, 0x91, 0xe8, 0xc9, 0x0d, 0xf0, - 0x13, 0xcc, 0xb3, 0x02, 0xb0, 0xbf, 0xcd, 0xb4, - - 0x02, 0x90, 0xbc, 0xcd, 0xb5, 0x02, 0xf0, 0xb8, - 0x90, 0xb6, 0xb0, 0xb3, 0x20, 0xe7, 0xff, 0x20, - - 0x7e, 0xe5, 0xa5, 0xff, 0x2a, 0x60, 0x58, 0x78, - 0x24, 0xff, 0x30, 0x30, 0x2c, 0xd2, 0x02, 0x10, - - 0xf5, 0x20, 0xa4, 0xe1, 0xa0, 0x00, 0x84, 0xf1, - 0x09, 0xf0, 0xd0, 0x0e, 0xd0, 0x07, 0xa2, 0x32, - - 0x8e, 0x54, 0x02, 0xa2, 0x08, 0x69, 0xcf, 0x18, - 0x69, 0xe9, 0x86, 0xf0, 0xa8, 0xb9, 0x90, 0x01, - - 0xaa, 0x25, 0xf1, 0x45, 0xf0, 0x99, 0x90, 0x01, - 0xb9, 0x91, 0x01, 0xa8, 0x60, 0x64, 0x7f, 0x5b, - - 0x6d, 0xc9, 0xf6, 0xd2, 0xe4, 0x40, 0xad, 0x40, - 0x02, 0x58, 0x78, 0xcd, 0x40, 0x02, 0xf0, 0xf9, - - 0xbc, 0x01, 0x03, 0xbd, 0x00, 0x03, 0xaa, 0x60, - 0xa9, 0x10, 0x8d, 0x84, 0x02, 0xa2, 0x00, 0x9d, - - 0x00, 0x0b, 0xe8, 0xd0, 0xfa, 0x8e, 0x84, 0x02, - 0x60, 0x08, 0x78, 0xa9, 0x40, 0x20, 0xea, 0xe9, - - 0x30, 0x05, 0x18, 0xb8, 0x20, 0x68, 0xf0, 0x28, - 0x2a, 0x60, 0x90, 0x09, 0xa0, 0x07, 0x8c, 0x40, - - 0xfe, 0x88, 0x8c, 0x40, 0xfe, 0x24, 0xff, 0x60, - 0x08, 0x78, 0x8d, 0x40, 0xfe, 0x28, 0x60, 0x8a, - - 0x08, 0x78, 0x8d, 0x48, 0x02, 0x8d, 0x20, 0xfe, - 0xad, 0x53, 0x02, 0x8d, 0x51, 0x02, 0x28, 0x60, - - 0x8a, 0x49, 0x07, 0x08, 0x78, 0x8d, 0x49, 0x02, - 0x8d, 0x21, 0xfe, 0x28, 0x60, 0x18, 0x66, 0xe4, - - 0x20, 0x3a, 0xe0, 0xc8, 0xc9, 0x22, 0xf0, 0x02, - 0x88, 0x18, 0x66, 0xe4, 0xc9, 0x0d, 0x60, 0xa9, - - 0x00, 0x85, 0xe5, 0xb1, 0xf2, 0xc9, 0x0d, 0xd0, - 0x06, 0x24, 0xe4, 0x30, 0x52, 0x10, 0x1b, 0xc9, - - 0x20, 0x90, 0x4c, 0xd0, 0x06, 0x24, 0xe4, 0x30, - 0x40, 0x50, 0x0f, 0xc9, 0x22, 0xd0, 0x10, 0x24, - - 0xe4, 0x10, 0x36, 0xc8, 0xb1, 0xf2, 0xc9, 0x22, - 0xf0, 0x2f, 0x20, 0x3a, 0xe0, 0x38, 0x60, 0xc9, - - 0x7c, 0xd0, 0x26, 0xc8, 0xb1, 0xf2, 0xc9, 0x7c, - 0xf0, 0x1f, 0xc9, 0x22, 0xf0, 0x1b, 0xc9, 0x21, - - 0xd0, 0x05, 0xc8, 0xa9, 0x80, 0xd0, 0xba, 0xc9, - 0x20, 0x90, 0x14, 0xc9, 0x3f, 0xf0, 0x08, 0x20, - - 0xbf, 0xea, 0x2c, 0xb7, 0xd9, 0x70, 0x03, 0xa9, - 0x7f, 0xb8, 0xc8, 0x05, 0xe5, 0x18, 0x60, 0x00, - - 0xfd, 0x42, 0x61, 0x64, 0x20, 0x73, 0x74, 0x72, - 0x69, 0x6e, 0x67, 0x00, 0xc9, 0x30, 0xf0, 0x1e, - - 0xc9, 0x40, 0xf0, 0x1a, 0x90, 0x12, 0xc9, 0x7f, - 0xf0, 0x14, 0xb0, 0x10, 0x49, 0x30, 0xc9, 0x6f, - - 0xf0, 0x04, 0xc9, 0x50, 0xd0, 0x02, 0x49, 0x1f, - 0xc9, 0x21, 0x90, 0x02, 0x49, 0x10, 0x60, 0xc9, - - 0x7f, 0xf0, 0x0e, 0xb0, 0xe7, 0xc9, 0x60, 0xd0, - 0x02, 0xa9, 0x5f, 0xc9, 0x40, 0x90, 0x02, 0x29, - - 0x1f, 0x60, 0x2f, 0x21, 0x42, 0x4f, 0x4f, 0x54, - 0x0d, 0xad, 0x87, 0x02, 0x49, 0x4c, 0xd0, 0x13, - - 0x4c, 0x87, 0x02, 0xad, 0x90, 0x02, 0x8e, 0x90, - 0x02, 0xaa, 0x98, 0x29, 0x01, 0xac, 0x91, 0x02, - - 0x8d, 0x91, 0x02, 0x60, 0x98, 0x9d, 0x00, 0xfc, - 0x60, 0x98, 0x9d, 0x00, 0xfd, 0x60, 0x98, 0x9d, - - 0x00, 0xfe, 0x60, 0xa9, 0x04, 0x9d, 0x08, 0x08, - 0xa9, 0xc0, 0x9d, 0x04, 0x08, 0xac, 0x62, 0x02, - - 0xf0, 0x02, 0xa9, 0xc0, 0x38, 0xe9, 0x40, 0x4a, - 0x4a, 0x4a, 0x49, 0x0f, 0x1d, 0x3c, 0xeb, 0x09, - - 0x10, 0x08, 0x78, 0xa0, 0xff, 0x8c, 0x43, 0xfe, - 0x8d, 0x4f, 0xfe, 0xc8, 0x8c, 0x40, 0xfe, 0xa0, - - 0x02, 0x88, 0xd0, 0xfd, 0xa0, 0x08, 0x8c, 0x40, - 0xfe, 0xa0, 0x04, 0x88, 0xd0, 0xfd, 0x28, 0x60, - - 0xe0, 0xc0, 0xa0, 0x80, 0x4c, 0x59, 0xec, 0xa9, - 0x00, 0x8d, 0x3b, 0x08, 0xad, 0x38, 0x08, 0xd0, - - 0x06, 0xee, 0x3b, 0x08, 0xce, 0x38, 0x08, 0xa2, - 0x08, 0xca, 0xbd, 0x00, 0x08, 0xf0, 0xe5, 0xbd, - - 0xcf, 0x02, 0x30, 0x05, 0xbd, 0x18, 0x08, 0xd0, - 0x03, 0x20, 0x6b, 0xec, 0xbd, 0x18, 0x08, 0xf0, - - 0x13, 0xc9, 0xff, 0xf0, 0x12, 0xde, 0x1c, 0x08, - 0xd0, 0x0d, 0xa9, 0x05, 0x9d, 0x1c, 0x08, 0xde, - - 0x18, 0x08, 0xd0, 0x03, 0x20, 0x6b, 0xec, 0xbd, - 0x24, 0x08, 0xf0, 0x05, 0xde, 0x24, 0x08, 0xd0, - - 0xb3, 0xbc, 0x20, 0x08, 0xc0, 0xff, 0xf0, 0xac, - 0xb9, 0xc0, 0x08, 0x29, 0x7f, 0x9d, 0x24, 0x08, - - 0xbd, 0x08, 0x08, 0xc9, 0x04, 0xf0, 0x60, 0xbd, - 0x08, 0x08, 0x18, 0x7d, 0x20, 0x08, 0xa8, 0xb9, - - 0xcb, 0x08, 0x38, 0xe9, 0x3f, 0x8d, 0x3a, 0x08, - 0xb9, 0xc7, 0x08, 0x8d, 0x39, 0x08, 0xbd, 0x04, - - 0x08, 0x48, 0x18, 0x6d, 0x39, 0x08, 0x50, 0x07, - 0x2a, 0xa9, 0x3f, 0xb0, 0x02, 0x49, 0xff, 0x9d, - - 0x04, 0x08, 0x2a, 0x5d, 0x04, 0x08, 0x10, 0x09, - 0xa9, 0x3f, 0x90, 0x02, 0x49, 0xff, 0x9d, 0x04, - - 0x08, 0xce, 0x39, 0x08, 0xbd, 0x04, 0x08, 0x38, - 0xed, 0x3a, 0x08, 0x4d, 0x39, 0x08, 0x30, 0x09, - - 0xad, 0x3a, 0x08, 0x9d, 0x04, 0x08, 0xfe, 0x08, - 0x08, 0x68, 0x5d, 0x04, 0x08, 0x29, 0xf8, 0xf0, - - 0x06, 0xbd, 0x04, 0x08, 0x20, 0x0a, 0xeb, 0xbd, - 0x10, 0x08, 0xc9, 0x03, 0xf0, 0x4b, 0xbd, 0x14, - - 0x08, 0xd0, 0x2a, 0xfe, 0x10, 0x08, 0xbd, 0x10, - 0x08, 0xc9, 0x03, 0xd0, 0x10, 0xbc, 0x20, 0x08, - - 0xb9, 0xc0, 0x08, 0x30, 0x34, 0xa9, 0x00, 0x9d, - 0x30, 0x08, 0x9d, 0x10, 0x08, 0xbd, 0x10, 0x08, - - 0x18, 0x7d, 0x20, 0x08, 0xa8, 0xb9, 0xc4, 0x08, - 0x9d, 0x14, 0x08, 0xf0, 0x1c, 0xde, 0x14, 0x08, - - 0xbd, 0x20, 0x08, 0x18, 0x7d, 0x10, 0x08, 0xa8, - 0xb9, 0xc1, 0x08, 0x18, 0x7d, 0x30, 0x08, 0x9d, - - 0x30, 0x08, 0x18, 0x7d, 0x0c, 0x08, 0x20, 0x01, - 0xed, 0xe0, 0x04, 0xf0, 0x0d, 0x4c, 0x59, 0xeb, - - 0xa2, 0x08, 0xca, 0x20, 0xa2, 0xec, 0xe0, 0x04, - 0xd0, 0xf8, 0x60, 0xbd, 0x08, 0x08, 0xc9, 0x04, - - 0xf0, 0x05, 0xa9, 0x03, 0x9d, 0x08, 0x08, 0xbd, - 0xcf, 0x02, 0xf0, 0x14, 0xa9, 0x00, 0x9d, 0xcf, - - 0x02, 0xa0, 0x04, 0x99, 0x2b, 0x08, 0x88, 0xd0, - 0xfa, 0x9d, 0x18, 0x08, 0x88, 0x8c, 0x38, 0x08, - - 0xbd, 0x28, 0x08, 0xf0, 0x46, 0xad, 0x3b, 0x08, - 0xf0, 0x36, 0xa9, 0x00, 0x9d, 0x28, 0x08, 0x4c, - - 0x98, 0xed, 0x20, 0x03, 0xeb, 0x98, 0x9d, 0x18, - 0x08, 0x9d, 0xcf, 0x02, 0x9d, 0x00, 0x08, 0xa0, - - 0x03, 0x99, 0x2c, 0x08, 0x88, 0x10, 0xfa, 0x8c, - 0x38, 0x08, 0x30, 0x4a, 0x08, 0x78, 0xbd, 0x08, - - 0x08, 0xc9, 0x04, 0xd0, 0x0a, 0x20, 0x5b, 0xe4, - 0x90, 0x05, 0xa9, 0x00, 0x9d, 0x00, 0x08, 0x28, - - 0xbc, 0x20, 0x08, 0xc0, 0xff, 0xd0, 0x03, 0x20, - 0x03, 0xeb, 0x60, 0x20, 0x5b, 0xe4, 0xb0, 0xdc, - - 0x29, 0x03, 0xf0, 0xbb, 0xad, 0x38, 0x08, 0xf0, - 0x15, 0xfe, 0x28, 0x08, 0x2c, 0x38, 0x08, 0x10, - - 0x0a, 0x20, 0x5b, 0xe4, 0x29, 0x03, 0x8d, 0x38, - 0x08, 0x10, 0x03, 0xce, 0x38, 0x08, 0x4c, 0xd0, - - 0xec, 0xdd, 0x2c, 0x08, 0xf0, 0xd4, 0x9d, 0x2c, - 0x08, 0xe0, 0x04, 0xd0, 0x09, 0x29, 0x0f, 0x1d, - - 0x3c, 0xeb, 0x08, 0x4c, 0x95, 0xed, 0x48, 0x29, - 0x03, 0x8d, 0x3c, 0x08, 0xa9, 0x00, 0x8d, 0x3d, - - 0x08, 0x68, 0x4a, 0x4a, 0xc9, 0x0c, 0x90, 0x07, - 0xee, 0x3d, 0x08, 0xe9, 0x0c, 0xd0, 0xf5, 0xa8, - - 0xad, 0x3d, 0x08, 0x48, 0xb9, 0xfb, 0xed, 0x8d, - 0x3d, 0x08, 0xb9, 0x07, 0xee, 0x48, 0x29, 0x03, - - 0x8d, 0x3e, 0x08, 0x68, 0x4a, 0x4a, 0x4a, 0x4a, - 0x8d, 0x3f, 0x08, 0xad, 0x3d, 0x08, 0xac, 0x3c, - - 0x08, 0xf0, 0x0c, 0x38, 0xed, 0x3f, 0x08, 0xb0, - 0x03, 0xce, 0x3e, 0x08, 0x88, 0xd0, 0xf4, 0x8d, - - 0x3d, 0x08, 0x68, 0xa8, 0xf0, 0x09, 0x4e, 0x3e, - 0x08, 0x6e, 0x3d, 0x08, 0x88, 0xd0, 0xf7, 0xad, - - 0x3d, 0x08, 0x18, 0x7d, 0x3d, 0xc4, 0x8d, 0x3d, - 0x08, 0x90, 0x03, 0xee, 0x3e, 0x08, 0x29, 0x0f, - - 0x1d, 0x3c, 0xeb, 0x08, 0x78, 0x20, 0x21, 0xeb, - 0xad, 0x3d, 0x08, 0x4e, 0x3e, 0x08, 0x6a, 0x4e, - - 0x3e, 0x08, 0x6a, 0x4a, 0x4a, 0x4c, 0x22, 0xeb, - 0x08, 0x78, 0x20, 0x60, 0xe4, 0x48, 0x29, 0x04, - - 0xf0, 0x15, 0x68, 0xbc, 0x20, 0x08, 0xc0, 0xff, - 0xd0, 0x03, 0x20, 0x03, 0xeb, 0x20, 0x60, 0xe4, - - 0x20, 0x60, 0xe4, 0x28, 0x4c, 0xf7, 0xed, 0x68, - 0x29, 0xf8, 0x0a, 0x90, 0x0b, 0x49, 0xff, 0x4a, - - 0x38, 0xe9, 0x40, 0x20, 0x0a, 0xeb, 0xa9, 0xff, - 0x9d, 0x20, 0x08, 0xa9, 0x05, 0x9d, 0x1c, 0x08, - - 0xa9, 0x01, 0x9d, 0x24, 0x08, 0xa9, 0x00, 0x9d, - 0x14, 0x08, 0x9d, 0x08, 0x08, 0x9d, 0x30, 0x08, - - 0xa9, 0xff, 0x9d, 0x10, 0x08, 0x20, 0x60, 0xe4, - 0x9d, 0x0c, 0x08, 0x20, 0x60, 0xe4, 0x28, 0x48, - - 0xbd, 0x0c, 0x08, 0x20, 0x01, 0xed, 0x68, 0x9d, - 0x18, 0x08, 0x60, 0xf0, 0xb7, 0x82, 0x4f, 0x20, - - 0xf3, 0xc8, 0xa0, 0x7b, 0x57, 0x35, 0x16, 0xe7, - 0xd7, 0xcb, 0xc3, 0xb7, 0xaa, 0xa2, 0x9a, 0x92, - - 0x8a, 0x82, 0x7a, 0xa9, 0xef, 0x85, 0xf5, 0x60, - 0xa2, 0x0d, 0xe6, 0xf5, 0xa4, 0xf5, 0x10, 0x39, - - 0xa2, 0x00, 0x86, 0xf7, 0xe8, 0x86, 0xf6, 0x20, - 0xbb, 0xee, 0xa2, 0x03, 0x20, 0x62, 0xee, 0xdd, - - 0x0c, 0xdf, 0xd0, 0xe4, 0xca, 0x10, 0xf5, 0xa9, - 0x3e, 0x85, 0xf6, 0x20, 0xbb, 0xee, 0xa2, 0xff, - - 0x20, 0x62, 0xee, 0xa0, 0x08, 0x0a, 0x76, 0xf7, - 0x88, 0xd0, 0xfa, 0xe8, 0xf0, 0xf2, 0x18, 0x90, - - 0x6a, 0xa2, 0x0e, 0xa4, 0xf5, 0x30, 0x0b, 0xa0, - 0xff, 0x08, 0x20, 0x68, 0xf1, 0x28, 0xc9, 0x01, - - 0x98, 0x60, 0x08, 0x78, 0xa0, 0x10, 0x20, 0x7f, - 0xee, 0xa0, 0x00, 0xf0, 0x17, 0xa0, 0x00, 0xf0, - - 0x11, 0x48, 0x20, 0x7a, 0xee, 0x68, 0x6a, 0x6a, - 0x6a, 0x6a, 0x29, 0x0f, 0x09, 0x40, 0xa8, 0x98, - - 0xa0, 0x01, 0x08, 0x78, 0x2c, 0x7b, 0x02, 0x10, - 0x21, 0x48, 0xb9, 0x75, 0xf0, 0x8d, 0x43, 0xfe, - - 0x68, 0x8d, 0x4f, 0xfe, 0xb9, 0x77, 0xf0, 0x8d, - 0x40, 0xfe, 0x2c, 0x40, 0xfe, 0x30, 0xfb, 0xad, - - 0x4f, 0xfe, 0x48, 0xb9, 0x79, 0xf0, 0x8d, 0x40, - 0xfe, 0x68, 0x28, 0xa8, 0x60, 0xad, 0xcb, 0x03, - - 0x85, 0xf6, 0xad, 0xcc, 0x03, 0x85, 0xf7, 0xa5, - 0xf5, 0x10, 0x1e, 0x08, 0x78, 0xa5, 0xf6, 0x20, - - 0x71, 0xee, 0xa5, 0xf5, 0x85, 0xfa, 0xa5, 0xf7, - 0x2a, 0x2a, 0x46, 0xfa, 0x6a, 0x46, 0xfa, 0x6a, - - 0x20, 0x71, 0xee, 0xa5, 0xfa, 0x20, 0x7a, 0xee, - 0x28, 0x60, 0xa2, 0xff, 0xa5, 0xec, 0x05, 0xed, - - 0xd0, 0x06, 0xa9, 0x81, 0x8d, 0x4e, 0xfe, 0xe8, - 0x8e, 0x42, 0x02, 0x08, 0xad, 0x5a, 0x02, 0x4a, - - 0x29, 0x18, 0x09, 0x06, 0x8d, 0x40, 0xfe, 0x4a, - 0x09, 0x07, 0x8d, 0x40, 0xfe, 0x20, 0x2e, 0xf1, - - 0x68, 0x60, 0x50, 0x0a, 0xa9, 0x01, 0x8d, 0x4e, - 0xfe, 0xb0, 0x08, 0x4c, 0x0f, 0xf0, 0x90, 0x06, - - 0x4c, 0xd1, 0xf0, 0xee, 0x42, 0x02, 0xad, 0x5a, - 0x02, 0x29, 0xb7, 0xa2, 0x00, 0x20, 0x2a, 0xf0, - - 0x86, 0xfa, 0xb8, 0x10, 0x05, 0x2c, 0xb7, 0xd9, - 0x09, 0x08, 0xe8, 0x20, 0x2a, 0xf0, 0x90, 0xbb, - - 0x10, 0x02, 0x09, 0x40, 0x8d, 0x5a, 0x02, 0xa6, - 0xec, 0xf0, 0x12, 0x20, 0x2a, 0xf0, 0x30, 0x10, - - 0xe4, 0xec, 0x86, 0xec, 0xd0, 0x07, 0xa2, 0x00, - 0x86, 0xec, 0x20, 0x1f, 0xf0, 0x4c, 0xe9, 0xef, - - 0xe4, 0xec, 0xd0, 0xee, 0xa5, 0xe7, 0xf0, 0x23, - 0xc6, 0xe7, 0xd0, 0x1f, 0xad, 0xca, 0x02, 0x85, - - 0xe7, 0xad, 0x55, 0x02, 0x8d, 0xca, 0x02, 0xad, - 0x5a, 0x02, 0xa6, 0xec, 0xe0, 0xd0, 0xd0, 0x0e, - - 0x09, 0x90, 0x49, 0xa0, 0x8d, 0x5a, 0x02, 0xa9, - 0x00, 0x85, 0xe7, 0x4c, 0xe9, 0xef, 0xe0, 0xc0, - - 0xd0, 0x0f, 0x09, 0xa0, 0x24, 0xfa, 0x10, 0x04, - 0x09, 0x10, 0x49, 0x80, 0x49, 0x90, 0x4c, 0x74, - - 0xef, 0xbd, 0xab, 0xef, 0xd0, 0x03, 0xad, 0x6b, - 0x02, 0xae, 0x5a, 0x02, 0x86, 0xfa, 0x26, 0xfa, - - 0x10, 0x07, 0xa6, 0xed, 0xd0, 0xa4, 0x20, 0xbf, - 0xea, 0x26, 0xfa, 0x30, 0x08, 0x20, 0x9c, 0xea, - - 0x26, 0xfa, 0x4c, 0xc1, 0xef, 0x26, 0xfa, 0x30, - 0x0d, 0x20, 0xe3, 0xe4, 0xb0, 0x08, 0x20, 0x9c, - - 0xea, 0xae, 0x5a, 0x02, 0x10, 0x0b, 0x26, 0xfa, - 0x10, 0x07, 0xa6, 0xed, 0xd0, 0xd6, 0x20, 0x9c, - - 0xea, 0xcd, 0x6c, 0x02, 0xd0, 0x07, 0xae, 0x75, - 0x02, 0xd0, 0x02, 0x86, 0xe7, 0xa8, 0x20, 0x29, - - 0xf1, 0xad, 0x59, 0x02, 0xd0, 0x03, 0x20, 0xf1, - 0xe4, 0xa6, 0xed, 0xf0, 0x0b, 0x20, 0x2a, 0xf0, - - 0x86, 0xed, 0x30, 0x04, 0xa2, 0x00, 0x86, 0xed, - 0xa6, 0xed, 0xd0, 0x16, 0xa0, 0xec, 0x20, 0xcc, - - 0xf0, 0x30, 0x09, 0xa5, 0xec, 0x85, 0xed, 0x86, - 0xec, 0x20, 0x1f, 0xf0, 0x4c, 0xda, 0xee, 0x20, - - 0x2a, 0xf0, 0xa5, 0xec, 0xd0, 0xf6, 0xa0, 0xed, - 0x20, 0xcc, 0xf0, 0x30, 0xef, 0x10, 0xe8, 0xa2, - - 0x01, 0x86, 0xe7, 0xae, 0x54, 0x02, 0x8e, 0xca, - 0x02, 0x60, 0xa0, 0x03, 0x8c, 0x40, 0xfe, 0xa0, - - 0x7f, 0x8c, 0x43, 0xfe, 0x8e, 0x4f, 0xfe, 0xae, - 0x4f, 0xfe, 0x60, 0x71, 0x33, 0x34, 0x35, 0x84, - - 0x38, 0x87, 0x2d, 0x5e, 0x8c, 0x84, 0xec, 0x86, - 0xed, 0x60, 0x00, 0x80, 0x77, 0x65, 0x74, 0x37, - - 0x69, 0x39, 0x30, 0x5f, 0x8e, 0x6c, 0xfe, 0xfd, - 0x6c, 0xfa, 0x00, 0x31, 0x32, 0x64, 0x72, 0x36, - - 0x75, 0x6f, 0x70, 0x5b, 0x8f, 0x2c, 0xb7, 0xd9, - 0x6c, 0x28, 0x02, 0x01, 0x61, 0x78, 0x66, 0x79, - - 0x6a, 0x6b, 0x40, 0x3a, 0x0d, 0x00, 0xff, 0x01, - 0x02, 0x09, 0x0a, 0x02, 0x73, 0x63, 0x67, 0x68, - - 0x6e, 0x6c, 0x3b, 0x5d, 0x7f, 0xac, 0x44, 0x02, - 0xa2, 0x00, 0x60, 0x00, 0x7a, 0x20, 0x76, 0x62, - - 0x6d, 0x2c, 0x2e, 0x2f, 0x8b, 0xae, 0x41, 0x02, - 0x4c, 0xad, 0xe1, 0x1b, 0x81, 0x82, 0x83, 0x85, - - 0x86, 0x88, 0x89, 0x5c, 0x8d, 0x6c, 0x20, 0x02, - 0xd0, 0xeb, 0xa2, 0x08, 0x58, 0x78, 0x20, 0xb4, - - 0xf0, 0xca, 0x10, 0xf8, 0xe0, 0x09, 0x90, 0xe0, - 0x60, 0xa2, 0x09, 0x20, 0x68, 0xf1, 0x20, 0x4a, - - 0xfa, 0x0d, 0x4f, 0x53, 0x20, 0x31, 0x2e, 0x32, - 0x30, 0x0d, 0x00, 0x60, 0x18, 0xa2, 0x10, 0xb0, - - 0x97, 0x8a, 0x10, 0x05, 0x20, 0x2a, 0xf0, 0xb0, - 0x55, 0x08, 0x90, 0x02, 0xa0, 0xee, 0x99, 0xdf, - - 0x01, 0xa2, 0x09, 0x20, 0x29, 0xf1, 0xa9, 0x7f, - 0x8d, 0x43, 0xfe, 0xa9, 0x03, 0x8d, 0x40, 0xfe, - - 0xa9, 0x0f, 0x8d, 0x4f, 0xfe, 0xa9, 0x01, 0x8d, - 0x4d, 0xfe, 0x8e, 0x4f, 0xfe, 0x2c, 0x4d, 0xfe, - - 0xf0, 0x21, 0x8a, 0xd9, 0xdf, 0x01, 0x90, 0x16, - 0x8d, 0x4f, 0xfe, 0x2c, 0x4f, 0xfe, 0x10, 0x0e, - - 0x28, 0x08, 0xb0, 0x13, 0x48, 0x59, 0x00, 0x00, - 0x0a, 0xc9, 0x01, 0x68, 0xb0, 0x09, 0x18, 0x69, - - 0x10, 0x10, 0xe0, 0xca, 0x10, 0xbd, 0x8a, 0xaa, - 0x28, 0x20, 0x2e, 0xf1, 0x58, 0x78, 0xa9, 0x0b, - - 0x8d, 0x40, 0xfe, 0x8a, 0x60, 0x49, 0x8c, 0x0a, - 0x8d, 0x47, 0x02, 0xe0, 0x03, 0x4c, 0x4b, 0xf1, - - 0x08, 0xa9, 0xa1, 0x85, 0xe3, 0xa9, 0x19, 0x8d, - 0xd1, 0x03, 0x28, 0x08, 0xa9, 0x06, 0x20, 0x31, - - 0xe0, 0xa2, 0x06, 0x28, 0xf0, 0x01, 0xca, 0x86, - 0xc6, 0xa2, 0x0e, 0xbd, 0x51, 0xd9, 0x9d, 0x11, - - 0x02, 0xca, 0xd0, 0xf7, 0x86, 0xc2, 0xa2, 0x0f, - 0xa5, 0xf4, 0x48, 0x8a, 0xa2, 0x0f, 0xfe, 0xa1, - - 0x02, 0xde, 0xa1, 0x02, 0x10, 0x0d, 0x86, 0xf4, - 0x8e, 0x30, 0xfe, 0x20, 0x03, 0x80, 0xaa, 0xf0, - - 0x05, 0xa6, 0xf4, 0xca, 0x10, 0xe8, 0x68, 0x85, - 0xf4, 0x8d, 0x30, 0xfe, 0x8a, 0x60, 0x09, 0x00, - - 0xd0, 0x10, 0xc0, 0x00, 0xd0, 0x0c, 0xa5, 0xc6, - 0x29, 0xfb, 0x0d, 0x47, 0x02, 0x0a, 0x0d, 0x47, - - 0x02, 0x4a, 0x60, 0x4c, 0xf5, 0x1d, 0xf6, 0x04, - 0xf3, 0x0f, 0xe3, 0x04, 0xf3, 0x2a, 0xf3, 0x74, - - 0xe2, 0xc9, 0x07, 0xb0, 0xed, 0x86, 0xbc, 0x0a, - 0xaa, 0xbd, 0xa4, 0xf1, 0x48, 0xbd, 0xa3, 0xf1, - - 0x48, 0xa6, 0xbc, 0x60, 0x08, 0x48, 0x20, 0x27, - 0xfb, 0xad, 0xc2, 0x03, 0x48, 0x20, 0x31, 0xf6, - - 0x68, 0xf0, 0x1a, 0xa2, 0x03, 0xa9, 0xff, 0x48, - 0xbd, 0xbe, 0x03, 0x95, 0xb0, 0x68, 0x35, 0xb0, - - 0xca, 0x10, 0xf4, 0xc9, 0xff, 0xd0, 0x06, 0x20, - 0xe8, 0xfa, 0x4c, 0x67, 0xe2, 0xad, 0xca, 0x03, - - 0x4a, 0x68, 0xf0, 0x0e, 0x90, 0x13, 0x20, 0xf2, - 0xfa, 0x00, 0xd5, 0x4c, 0x6f, 0x63, 0x6b, 0x65, - - 0x64, 0x00, 0x90, 0x05, 0xa9, 0x03, 0x8d, 0x58, - 0x02, 0xa9, 0x30, 0x25, 0xbb, 0xf0, 0x04, 0xa5, - - 0xc1, 0xd0, 0x0a, 0x98, 0x48, 0x20, 0xbb, 0xfb, - 0x68, 0xa8, 0x20, 0xd5, 0xf7, 0x20, 0xb4, 0xf9, - - 0xd0, 0x33, 0x20, 0x69, 0xfb, 0x2c, 0xca, 0x03, - 0x30, 0x08, 0x20, 0x6a, 0xf9, 0x20, 0x7b, 0xf7, - - 0xd0, 0xd7, 0xa0, 0x0a, 0xa5, 0xcc, 0x91, 0xc8, - 0xc8, 0xa5, 0xcd, 0x91, 0xc8, 0xa9, 0x00, 0xc8, - - 0x91, 0xc8, 0xc8, 0x91, 0xc8, 0x28, 0x20, 0xe8, - 0xfa, 0x24, 0xba, 0x30, 0x07, 0x08, 0x20, 0x46, - - 0xfa, 0x0d, 0x00, 0x28, 0x60, 0x20, 0x37, 0xf6, - 0xd0, 0xaf, 0x86, 0xf2, 0x84, 0xf3, 0xa0, 0x00, - - 0x20, 0x1d, 0xea, 0xa2, 0x00, 0x20, 0x2f, 0xea, - 0xb0, 0x0d, 0xf0, 0x08, 0x9d, 0xd2, 0x03, 0xe8, - - 0xe0, 0x0b, 0xd0, 0xf1, 0x4c, 0x8f, 0xea, 0xa9, - 0x00, 0x9d, 0xd2, 0x03, 0x60, 0x48, 0x86, 0xc8, - - 0x84, 0xc9, 0xa0, 0x00, 0xb1, 0xc8, 0xaa, 0xc8, - 0xb1, 0xc8, 0xa8, 0x20, 0x5a, 0xf2, 0xa0, 0x02, - - 0xb1, 0xc8, 0x99, 0xbc, 0x03, 0x99, 0xae, 0x00, - 0xc8, 0xc0, 0x0a, 0xd0, 0xf3, 0x68, 0xf0, 0x07, - - 0xc9, 0xff, 0xd0, 0xb0, 0x4c, 0xc4, 0xf1, 0x8d, - 0xc6, 0x03, 0x8d, 0xc7, 0x03, 0xb1, 0xc8, 0x99, - - 0xa6, 0x00, 0xc8, 0xc0, 0x12, 0xd0, 0xf6, 0x8a, - 0xf0, 0xba, 0x20, 0x27, 0xfb, 0x20, 0x34, 0xf9, - - 0xa9, 0x00, 0x20, 0xbd, 0xfb, 0x20, 0xe2, 0xfb, - 0x38, 0xa2, 0xfd, 0xbd, 0xb7, 0xff, 0xfd, 0xb3, - - 0xff, 0x9d, 0xcb, 0x02, 0xe8, 0xd0, 0xf4, 0xa8, - 0xd0, 0x0e, 0xec, 0xc8, 0x03, 0xa9, 0x01, 0xed, - - 0xc9, 0x03, 0x90, 0x04, 0xa2, 0x80, 0xd0, 0x08, - 0xa9, 0x01, 0x8d, 0xc9, 0x03, 0x8e, 0xc8, 0x03, - - 0x8e, 0xca, 0x03, 0x20, 0xec, 0xf7, 0x30, 0x49, - 0x20, 0x6a, 0xf9, 0xee, 0xc6, 0x03, 0xd0, 0xc8, - - 0xee, 0xc7, 0x03, 0xd0, 0xc3, 0x20, 0x5a, 0xf2, - 0xa2, 0xff, 0x8e, 0xc2, 0x03, 0x20, 0xc4, 0xf1, - - 0x2c, 0x7a, 0x02, 0x10, 0x0a, 0xad, 0xc4, 0x03, - 0x2d, 0xc5, 0x03, 0xc9, 0xff, 0xd0, 0x03, 0x6c, - - 0xc2, 0x03, 0xa2, 0xc2, 0xa0, 0x03, 0xa9, 0x04, - 0x4c, 0xc7, 0xfb, 0xa9, 0x08, 0x20, 0x44, 0xf3, - - 0x20, 0x27, 0xfb, 0xa9, 0x00, 0x20, 0x48, 0xf3, - 0x20, 0xfc, 0xfa, 0xa9, 0xf7, 0x25, 0xe2, 0x85, - - 0xe2, 0x60, 0xa9, 0x40, 0x05, 0xe2, 0xd0, 0xf7, - 0x48, 0xad, 0x47, 0x02, 0xf0, 0x0b, 0x20, 0x13, - - 0xee, 0x20, 0x18, 0xee, 0x90, 0x03, 0xb8, 0x50, - 0x41, 0x20, 0x7b, 0xf7, 0xad, 0xc6, 0x03, 0x85, - - 0xb4, 0xad, 0xc7, 0x03, 0x85, 0xb5, 0xa2, 0xff, - 0x8e, 0xdf, 0x03, 0xe8, 0x86, 0xba, 0xf0, 0x06, - - 0x20, 0x69, 0xfb, 0x20, 0x7b, 0xf7, 0xad, 0x47, - 0x02, 0xf0, 0x02, 0x50, 0x1d, 0x68, 0x48, 0xf0, - - 0x2d, 0x20, 0x72, 0xfa, 0xd0, 0x16, 0xa9, 0x30, - 0x25, 0xbb, 0xf0, 0x0e, 0xad, 0xc6, 0x03, 0xc5, - - 0xb6, 0xd0, 0x09, 0xad, 0xc7, 0x03, 0xc5, 0xb7, - 0xd0, 0x02, 0x68, 0x60, 0xad, 0x47, 0x02, 0xf0, - - 0x0d, 0x20, 0xad, 0xee, 0xa9, 0xff, 0x8d, 0xc6, - 0x03, 0x8d, 0xc7, 0x03, 0xd0, 0xc2, 0x50, 0x05, - - 0xa9, 0xff, 0x20, 0xd7, 0xf7, 0xa2, 0x00, 0x20, - 0xd9, 0xf9, 0xad, 0x47, 0x02, 0xf0, 0x04, 0x24, - - 0xbb, 0x50, 0xde, 0x2c, 0xca, 0x03, 0x30, 0xdc, - 0x10, 0xa6, 0x85, 0xbc, 0x8a, 0x48, 0x98, 0x48, - - 0xa5, 0xbc, 0xd0, 0x1e, 0x98, 0xd0, 0x0c, 0x20, - 0x75, 0xe2, 0x20, 0x78, 0xf4, 0x46, 0xe2, 0x06, - - 0xe2, 0x90, 0x0c, 0x4a, 0xb0, 0xf7, 0x4a, 0xb0, - 0x03, 0x4c, 0xb1, 0xfb, 0x20, 0x78, 0xf4, 0x4c, - - 0x71, 0xf4, 0x20, 0x5a, 0xf2, 0x24, 0xbc, 0x50, - 0x3d, 0xa9, 0x00, 0x8d, 0x9e, 0x03, 0x8d, 0xdd, - - 0x03, 0x8d, 0xde, 0x03, 0xa9, 0x3e, 0x20, 0x3d, - 0xf3, 0x20, 0x1a, 0xfb, 0x08, 0x20, 0x31, 0xf6, - - 0x20, 0xb4, 0xf6, 0x28, 0xa2, 0xff, 0xe8, 0xbd, - 0xb2, 0x03, 0x9d, 0xa7, 0x03, 0xd0, 0xf7, 0xa9, - - 0x01, 0x20, 0x44, 0xf3, 0xad, 0xea, 0x02, 0x0d, - 0xeb, 0x02, 0xd0, 0x03, 0x20, 0x42, 0xf3, 0xa9, - - 0x01, 0x0d, 0x47, 0x02, 0xd0, 0x39, 0x8a, 0xd0, - 0x03, 0x4c, 0x8f, 0xea, 0xa2, 0xff, 0xe8, 0xbd, - - 0xd2, 0x03, 0x9d, 0x80, 0x03, 0xd0, 0xf7, 0xa9, - 0xff, 0xa2, 0x08, 0x9d, 0x8b, 0x03, 0xca, 0xd0, - - 0xfa, 0x8a, 0xa2, 0x14, 0x9d, 0x80, 0x03, 0xe8, - 0xe0, 0x1e, 0xd0, 0xf8, 0x2e, 0x97, 0x03, 0x20, - - 0x27, 0xfb, 0x20, 0x34, 0xf9, 0x20, 0xf2, 0xfa, - 0xa9, 0x02, 0x20, 0x44, 0xf3, 0xa9, 0x02, 0x85, - - 0xbc, 0x68, 0xa8, 0x68, 0xaa, 0xa5, 0xbc, 0x60, - 0xa9, 0x02, 0x25, 0xe2, 0xf0, 0xf9, 0xa9, 0x00, - - 0x8d, 0x97, 0x03, 0xa9, 0x80, 0xae, 0x9d, 0x03, - 0x8e, 0x96, 0x03, 0x8d, 0x98, 0x03, 0x20, 0x96, - - 0xf4, 0xa9, 0xfd, 0x4c, 0x3d, 0xf3, 0x20, 0x1a, - 0xfb, 0xa2, 0x11, 0xbd, 0x8c, 0x03, 0x9d, 0xbe, - - 0x03, 0xca, 0x10, 0xf7, 0x86, 0xb2, 0x86, 0xb3, - 0xe8, 0x86, 0xb0, 0xa9, 0x09, 0x85, 0xb1, 0xa2, - - 0x7f, 0x20, 0x81, 0xfb, 0x8d, 0xdf, 0x03, 0x20, - 0x8e, 0xfb, 0x20, 0xe2, 0xfb, 0x20, 0xec, 0xf7, - - 0xee, 0x94, 0x03, 0xd0, 0x03, 0xee, 0x95, 0x03, - 0x60, 0x8a, 0x48, 0x98, 0x48, 0xa9, 0x01, 0x20, - - 0x9c, 0xfb, 0xa5, 0xe2, 0x0a, 0xb0, 0x4c, 0x0a, - 0x90, 0x09, 0xa9, 0x80, 0x20, 0x44, 0xf3, 0xa9, - - 0xfe, 0xb0, 0x38, 0xae, 0x9e, 0x03, 0xe8, 0xec, - 0xea, 0x02, 0xd0, 0x2a, 0x2c, 0xec, 0x02, 0x30, - - 0x22, 0xad, 0xed, 0x02, 0x48, 0x20, 0x1a, 0xfb, - 0x08, 0x20, 0xac, 0xf6, 0x28, 0x68, 0x85, 0xbc, - - 0x18, 0x2c, 0xec, 0x02, 0x10, 0x17, 0xad, 0xea, - 0x02, 0x0d, 0xeb, 0x02, 0xd0, 0x0f, 0x20, 0x42, - - 0xf3, 0xd0, 0x0a, 0x20, 0x42, 0xf3, 0xca, 0x18, - 0xbd, 0x00, 0x0a, 0x85, 0xbc, 0xee, 0x9e, 0x03, - - 0x4c, 0x71, 0xf4, 0x00, 0xdf, 0x45, 0x4f, 0x46, - 0x00, 0x85, 0xc4, 0x8a, 0x48, 0x98, 0x48, 0xa9, - - 0x02, 0x20, 0x9c, 0xfb, 0xae, 0x9d, 0x03, 0xa5, - 0xc4, 0x9d, 0x00, 0x09, 0xe8, 0xd0, 0x06, 0x20, - - 0x96, 0xf4, 0x20, 0xf2, 0xfa, 0xee, 0x9d, 0x03, - 0xa5, 0xc4, 0x4c, 0x6f, 0xf4, 0x8a, 0xf0, 0x2e, - - 0xe0, 0x03, 0xf0, 0x1f, 0xc0, 0x03, 0xb0, 0x06, - 0xca, 0xf0, 0x06, 0xca, 0xf0, 0x0a, 0x4c, 0x10, - - 0xe3, 0xa9, 0x33, 0xc8, 0xc8, 0xc8, 0xd0, 0x02, - 0xa9, 0xcc, 0xc8, 0x25, 0xe3, 0x19, 0x81, 0xf5, - - 0x85, 0xe3, 0x60, 0x98, 0x30, 0x02, 0xd0, 0x02, - 0xa9, 0x19, 0x8d, 0xd1, 0x03, 0x60, 0xa8, 0xf0, - - 0xec, 0xa1, 0x00, 0x22, 0x11, 0x00, 0x88, 0xcc, - 0xc6, 0xc0, 0xad, 0x47, 0x02, 0xf0, 0x07, 0x20, - - 0x51, 0xee, 0xa8, 0x18, 0x90, 0x1a, 0xad, 0x08, - 0xfe, 0x48, 0x29, 0x02, 0xf0, 0x0b, 0xa4, 0xca, - - 0xf0, 0x07, 0x68, 0xa5, 0xbd, 0x8d, 0x09, 0xfe, - 0x60, 0xac, 0x09, 0xfe, 0x68, 0x4a, 0x4a, 0x4a, - - 0xa6, 0xc2, 0xf0, 0x69, 0xca, 0xd0, 0x06, 0x90, - 0x64, 0xa0, 0x02, 0xd0, 0x5e, 0xca, 0xd0, 0x13, - - 0xb0, 0x5b, 0x98, 0x20, 0x78, 0xfb, 0xa0, 0x03, - 0xc9, 0x2a, 0xf0, 0x4f, 0x20, 0x50, 0xfb, 0xa0, - - 0x01, 0xd0, 0x48, 0xca, 0xd0, 0x0c, 0xb0, 0x04, - 0x84, 0xbd, 0xf0, 0x41, 0xa9, 0x80, 0x85, 0xc0, - - 0xd0, 0x3b, 0xca, 0xd0, 0x29, 0xb0, 0x2f, 0x98, - 0x20, 0xb0, 0xf7, 0xa4, 0xbc, 0xe6, 0xbc, 0x24, - - 0xbd, 0x30, 0x0d, 0x20, 0xd3, 0xfb, 0xf0, 0x05, - 0x8e, 0xe5, 0xfe, 0xd0, 0x03, 0x8a, 0x91, 0xb0, - - 0xc8, 0xcc, 0xc8, 0x03, 0xd0, 0x17, 0xa9, 0x01, - 0x85, 0xbc, 0xa0, 0x05, 0xd0, 0x0d, 0x98, 0x20, - - 0xb0, 0xf7, 0xc6, 0xbc, 0x10, 0x07, 0x20, 0x46, - 0xfb, 0xa0, 0x00, 0x84, 0xc2, 0x60, 0x48, 0x98, - - 0x48, 0x8a, 0xa8, 0xa9, 0x03, 0x20, 0x9c, 0xfb, - 0xa5, 0xe2, 0x29, 0x40, 0xaa, 0x68, 0xa8, 0x68, - - 0x60, 0xa9, 0x00, 0x85, 0xb4, 0x85, 0xb5, 0xa5, - 0xb4, 0x48, 0x85, 0xb6, 0xa5, 0xb5, 0x48, 0x85, - - 0xb7, 0x20, 0x46, 0xfa, 0x53, 0x65, 0x61, 0x72, - 0x63, 0x68, 0x69, 0x6e, 0x67, 0x0d, 0x00, 0xa9, - - 0xff, 0x20, 0x48, 0xf3, 0x68, 0x85, 0xb5, 0x68, - 0x85, 0xb4, 0xa5, 0xb6, 0x05, 0xb7, 0xd0, 0x0d, - - 0x85, 0xb4, 0x85, 0xb5, 0xa5, 0xc1, 0xd0, 0x05, - 0xa2, 0xb1, 0x20, 0x81, 0xfb, 0xad, 0x47, 0x02, - - 0xf0, 0x13, 0x70, 0x11, 0x00, 0xd6, 0x46, 0x69, - 0x6c, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x66, - - 0x6f, 0x75, 0x6e, 0x64, 0x00, 0xa0, 0xff, 0x8c, - 0xdf, 0x03, 0x60, 0xa9, 0x00, 0x08, 0x84, 0xe6, - - 0xac, 0x56, 0x02, 0x8d, 0x56, 0x02, 0xf0, 0x03, - 0x20, 0xce, 0xff, 0xa4, 0xe6, 0x28, 0xf0, 0x0b, - - 0xa9, 0x40, 0x20, 0xce, 0xff, 0xa8, 0xf0, 0xcc, - 0x8d, 0x56, 0x02, 0x60, 0xa2, 0xa6, 0x20, 0x81, - - 0xfb, 0x20, 0x7b, 0xf7, 0xad, 0xca, 0x03, 0x4a, - 0x90, 0x03, 0x4c, 0xf6, 0xf1, 0xad, 0xdd, 0x03, - - 0x85, 0xb4, 0xad, 0xde, 0x03, 0x85, 0xb5, 0xa9, - 0x00, 0x85, 0xb0, 0xa9, 0x0a, 0x85, 0xb1, 0xa9, - - 0xff, 0x85, 0xb2, 0x85, 0xb3, 0x20, 0xd5, 0xf7, - 0x20, 0xb4, 0xf9, 0xd0, 0x25, 0xad, 0xff, 0x0a, - - 0x8d, 0xed, 0x02, 0x20, 0x69, 0xfb, 0x8e, 0xdd, - 0x03, 0x8c, 0xde, 0x03, 0xa2, 0x02, 0xbd, 0xc8, - - 0x03, 0x9d, 0xea, 0x02, 0xca, 0x10, 0xf7, 0x2c, - 0xec, 0x02, 0x10, 0x03, 0x20, 0x49, 0xf2, 0x4c, - - 0xf2, 0xfa, 0x20, 0x37, 0xf6, 0xd0, 0xad, 0xc9, - 0x2a, 0xf0, 0x37, 0xc9, 0x23, 0xd0, 0x0f, 0xee, - - 0xc6, 0x03, 0xd0, 0x03, 0xee, 0xc7, 0x03, 0xa2, - 0xff, 0x2c, 0xb7, 0xd9, 0xd0, 0x55, 0xa9, 0xf7, - - 0x20, 0x3d, 0xf3, 0x00, 0xd7, 0x42, 0x61, 0x64, - 0x20, 0x52, 0x4f, 0x4d, 0x00, 0xa0, 0xff, 0x20, - - 0x90, 0xfb, 0xa9, 0x01, 0x85, 0xc2, 0x20, 0x50, - 0xfb, 0x20, 0x95, 0xf9, 0xa9, 0x03, 0xc5, 0xc2, - - 0xd0, 0xf7, 0xa0, 0x00, 0x20, 0x7c, 0xfb, 0x20, - 0x97, 0xf7, 0x50, 0x1a, 0x99, 0xb2, 0x03, 0xf0, - - 0x06, 0xc8, 0xc0, 0x0b, 0xd0, 0xf1, 0x88, 0xa2, - 0x0c, 0x20, 0x97, 0xf7, 0x50, 0x08, 0x9d, 0xb2, - - 0x03, 0xe8, 0xe0, 0x1f, 0xd0, 0xf3, 0x98, 0xaa, - 0xa9, 0x00, 0x99, 0xb2, 0x03, 0xa5, 0xbe, 0x05, - - 0xbf, 0x85, 0xc1, 0x20, 0x78, 0xfb, 0x84, 0xc2, - 0x8a, 0xd0, 0x59, 0xad, 0x47, 0x02, 0xf0, 0xad, - - 0x20, 0x51, 0xee, 0xc9, 0x2b, 0xd0, 0x80, 0xa9, - 0x08, 0x25, 0xe2, 0xf0, 0x03, 0x20, 0x4d, 0xf2, - - 0x20, 0x18, 0xee, 0x90, 0xeb, 0xb8, 0x60, 0xad, - 0x47, 0x02, 0xf0, 0x11, 0x8a, 0x48, 0x98, 0x48, - - 0x20, 0x51, 0xee, 0x85, 0xbd, 0xa9, 0xff, 0x85, - 0xc0, 0x68, 0xa8, 0x68, 0xaa, 0x20, 0x84, 0xf8, - - 0x08, 0x48, 0x38, 0x66, 0xcb, 0x45, 0xbf, 0x85, - 0xbf, 0xa5, 0xbf, 0x2a, 0x90, 0x0c, 0x6a, 0x49, - - 0x08, 0x85, 0xbf, 0xa5, 0xbe, 0x49, 0x10, 0x85, - 0xbe, 0x38, 0x26, 0xbe, 0x26, 0xbf, 0x46, 0xcb, - - 0xd0, 0xe7, 0x68, 0x28, 0x60, 0xa9, 0x00, 0x85, - 0xbd, 0xa2, 0x00, 0x86, 0xbc, 0x50, 0x0a, 0xad, - - 0xc8, 0x03, 0x0d, 0xc9, 0x03, 0xf0, 0x02, 0xa2, - 0x04, 0x86, 0xc2, 0x60, 0x08, 0xa2, 0x03, 0xa9, - - 0x00, 0x9d, 0xcb, 0x03, 0xca, 0x10, 0xfa, 0xad, - 0xc6, 0x03, 0x0d, 0xc7, 0x03, 0xd0, 0x05, 0x20, - - 0x92, 0xf8, 0xf0, 0x03, 0x20, 0x96, 0xf8, 0xa9, - 0x2a, 0x85, 0xbd, 0x20, 0x78, 0xfb, 0x20, 0x4a, - - 0xfb, 0x20, 0x84, 0xf8, 0x88, 0xc8, 0xb9, 0xd2, - 0x03, 0x99, 0xb2, 0x03, 0x20, 0x75, 0xf8, 0xd0, - - 0xf4, 0xa2, 0x0c, 0xbd, 0xb2, 0x03, 0x20, 0x75, - 0xf8, 0xe8, 0xe0, 0x1d, 0xd0, 0xf5, 0x20, 0x7b, - - 0xf8, 0xad, 0xc8, 0x03, 0x0d, 0xc9, 0x03, 0xf0, - 0x1c, 0xa0, 0x00, 0x20, 0x7c, 0xfb, 0xb1, 0xb0, - - 0x20, 0xd3, 0xfb, 0xf0, 0x03, 0xae, 0xe5, 0xfe, - 0x8a, 0x20, 0x75, 0xf8, 0xc8, 0xcc, 0xc8, 0x03, - - 0xd0, 0xec, 0x20, 0x7b, 0xf8, 0x20, 0x84, 0xf8, - 0x20, 0x84, 0xf8, 0x20, 0x46, 0xfb, 0xa9, 0x01, - - 0x20, 0x98, 0xf8, 0x28, 0x20, 0xb9, 0xf8, 0x2c, - 0xca, 0x03, 0x10, 0x08, 0x08, 0x20, 0x92, 0xf8, - - 0x20, 0x46, 0xf2, 0x28, 0x60, 0x20, 0x82, 0xf8, - 0x4c, 0xb0, 0xf7, 0xa5, 0xbf, 0x20, 0x82, 0xf8, - - 0xa5, 0xbe, 0x85, 0xbd, 0x20, 0x95, 0xf9, 0x24, - 0xc0, 0x10, 0xf9, 0xa9, 0x00, 0x85, 0xc0, 0xa5, - - 0xbd, 0x60, 0xa9, 0x32, 0xd0, 0x02, 0xa5, 0xc7, - 0xa2, 0x05, 0x8d, 0x40, 0x02, 0x20, 0x95, 0xf9, - - 0x2c, 0x40, 0x02, 0x10, 0xf8, 0xca, 0xd0, 0xf2, - 0x60, 0xad, 0xc6, 0x03, 0x0d, 0xc7, 0x03, 0xf0, - - 0x05, 0x2c, 0xdf, 0x03, 0x10, 0x03, 0x20, 0x49, - 0xf2, 0xa0, 0x00, 0x84, 0xba, 0xad, 0xca, 0x03, - - 0x8d, 0xdf, 0x03, 0x20, 0xdc, 0xe7, 0xf0, 0x6b, - 0xa9, 0x0d, 0x20, 0xee, 0xff, 0xb9, 0xb2, 0x03, - - 0xf0, 0x10, 0xc9, 0x20, 0x90, 0x04, 0xc9, 0x7f, - 0x90, 0x02, 0xa9, 0x3f, 0x20, 0xee, 0xff, 0xc8, - - 0xd0, 0xeb, 0xad, 0x47, 0x02, 0xf0, 0x04, 0x24, - 0xbb, 0x50, 0x48, 0x20, 0x91, 0xf9, 0xc8, 0xc0, - - 0x0b, 0x90, 0xef, 0xad, 0xc6, 0x03, 0xaa, 0x20, - 0x7a, 0xf9, 0x2c, 0xca, 0x03, 0x10, 0x34, 0x8a, - - 0x18, 0x6d, 0xc9, 0x03, 0x85, 0xcd, 0x20, 0x75, - 0xf9, 0xad, 0xc8, 0x03, 0x85, 0xcc, 0x20, 0x7a, - - 0xf9, 0x24, 0xbb, 0x50, 0x1e, 0xa2, 0x04, 0x20, - 0x91, 0xf9, 0xca, 0xd0, 0xfa, 0xa2, 0x0f, 0x20, - - 0x27, 0xf9, 0x20, 0x91, 0xf9, 0xa2, 0x13, 0xa0, - 0x04, 0xbd, 0xb2, 0x03, 0x20, 0x7a, 0xf9, 0xca, - - 0x88, 0xd0, 0xf6, 0x60, 0xad, 0x47, 0x02, 0xf0, - 0x03, 0x4c, 0x10, 0xe3, 0x20, 0x8e, 0xfb, 0x20, - - 0xe2, 0xfb, 0x20, 0xdc, 0xe7, 0xf0, 0xec, 0x20, - 0x46, 0xfa, 0x52, 0x45, 0x43, 0x4f, 0x52, 0x44, - - 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x52, 0x45, - 0x54, 0x55, 0x52, 0x4e, 0x00, 0x20, 0x95, 0xf9, - - 0x20, 0xe0, 0xff, 0xc9, 0x0d, 0xd0, 0xf6, 0x4c, - 0xe7, 0xff, 0xe6, 0xb1, 0xd0, 0x06, 0xe6, 0xb2, - - 0xd0, 0x02, 0xe6, 0xb3, 0x60, 0x48, 0x20, 0x91, - 0xf9, 0x68, 0x48, 0x4a, 0x4a, 0x4a, 0x4a, 0x20, - - 0x83, 0xf9, 0x68, 0x18, 0x29, 0x0f, 0x69, 0x30, - 0xc9, 0x3a, 0x90, 0x02, 0x69, 0x06, 0x4c, 0xee, - - 0xff, 0xa9, 0x20, 0xd0, 0xf9, 0x08, 0x24, 0xeb, - 0x30, 0x04, 0x24, 0xff, 0x30, 0x02, 0x28, 0x60, - - 0x20, 0x3b, 0xf3, 0x20, 0xf2, 0xfa, 0xa9, 0x7e, - 0x20, 0xf4, 0xff, 0x00, 0x11, 0x45, 0x73, 0x63, - - 0x61, 0x70, 0x65, 0x00, 0x98, 0xf0, 0x0d, 0x20, - 0x46, 0xfa, 0x0d, 0x4c, 0x6f, 0x61, 0x64, 0x69, - - 0x6e, 0x67, 0x0d, 0x00, 0x85, 0xba, 0xa2, 0xff, - 0xa5, 0xc1, 0xd0, 0x0d, 0x20, 0x72, 0xfa, 0x08, - - 0xa2, 0xff, 0xa0, 0x99, 0xa9, 0xfa, 0x28, 0xd0, - 0x1c, 0xa0, 0x8e, 0xa5, 0xc1, 0xf0, 0x04, 0xa9, - - 0xfa, 0xd0, 0x12, 0xad, 0xc6, 0x03, 0xc5, 0xb4, - 0xd0, 0x07, 0xad, 0xc7, 0x03, 0xc5, 0xb5, 0xf0, - - 0x13, 0xa0, 0xa4, 0xa9, 0xfa, 0x48, 0x98, 0x48, - 0x8a, 0x48, 0x20, 0xb6, 0xf8, 0x68, 0xaa, 0x68, - - 0xa8, 0x68, 0xd0, 0x14, 0x8a, 0x48, 0x20, 0xa9, - 0xf8, 0x20, 0xd6, 0xfa, 0x68, 0xaa, 0xa5, 0xbe, - - 0x05, 0xbf, 0xf0, 0x79, 0xa0, 0x8e, 0xa9, 0xfa, - 0xc6, 0xba, 0x48, 0x24, 0xeb, 0x30, 0x0d, 0x8a, - - 0x2d, 0x47, 0x02, 0xd0, 0x07, 0x8a, 0x29, 0x11, - 0x25, 0xbb, 0xf0, 0x10, 0x68, 0x85, 0xb9, 0x84, - - 0xb8, 0x20, 0x8b, 0xf6, 0x46, 0xeb, 0x20, 0xe8, - 0xfa, 0x6c, 0xb8, 0x00, 0x68, 0xc8, 0xd0, 0x03, - - 0x18, 0x69, 0x01, 0x48, 0x98, 0x48, 0x20, 0xdc, - 0xe7, 0xa8, 0x68, 0x85, 0xb8, 0x68, 0x85, 0xb9, - - 0x98, 0x08, 0xe6, 0xb8, 0xd0, 0x02, 0xe6, 0xb9, - 0xa0, 0x00, 0xb1, 0xb8, 0xf0, 0x0a, 0x28, 0x08, - - 0xf0, 0xf0, 0x20, 0xe3, 0xff, 0x4c, 0x52, 0xfa, - 0x28, 0xe6, 0xb8, 0xd0, 0x02, 0xe6, 0xb9, 0x6c, - - 0xb8, 0x00, 0xa2, 0xff, 0xe8, 0xbd, 0xd2, 0x03, - 0xd0, 0x07, 0x8a, 0xf0, 0x03, 0xbd, 0xb2, 0x03, - - 0x60, 0x20, 0xe3, 0xe4, 0x5d, 0xb2, 0x03, 0xb0, - 0x02, 0x29, 0xdf, 0xf0, 0xe7, 0x60, 0x00, 0xd8, - - 0x0d, 0x44, 0x61, 0x74, 0x61, 0x3f, 0x00, 0xd0, - 0x15, 0x00, 0xdb, 0x0d, 0x46, 0x69, 0x6c, 0x65, - - 0x3f, 0x00, 0xd0, 0x0a, 0x00, 0xda, 0x0d, 0x42, - 0x6c, 0x6f, 0x63, 0x6b, 0x3f, 0x00, 0xa5, 0xba, - - 0xf0, 0x21, 0x8a, 0xf0, 0x1e, 0xa9, 0x22, 0x24, - 0xbb, 0xf0, 0x18, 0x20, 0x46, 0xfb, 0xa8, 0x20, - - 0x4a, 0xfa, 0x0d, 0x07, 0x52, 0x65, 0x77, 0x69, - 0x6e, 0x64, 0x20, 0x74, 0x61, 0x70, 0x65, 0x0d, - - 0x0d, 0x00, 0x60, 0x20, 0x4d, 0xf2, 0xa5, 0xc2, - 0xf0, 0xf8, 0x20, 0x95, 0xf9, 0xad, 0x47, 0x02, - - 0xf0, 0xf4, 0x20, 0x88, 0xf5, 0x4c, 0xd6, 0xfa, - 0x20, 0xdc, 0xe7, 0xf0, 0x05, 0xa9, 0x07, 0x20, - - 0xee, 0xff, 0xa9, 0x80, 0x20, 0xbd, 0xfb, 0xa2, - 0x00, 0x20, 0x95, 0xfb, 0x08, 0x78, 0xad, 0x82, - - 0x02, 0x8d, 0x10, 0xfe, 0xa9, 0x00, 0x85, 0xea, - 0xf0, 0x01, 0x08, 0x20, 0x46, 0xfb, 0xad, 0x50, - - 0x02, 0x4c, 0x89, 0xe1, 0x28, 0x24, 0xff, 0x10, - 0x18, 0x60, 0xa5, 0xe3, 0x0a, 0x0a, 0x0a, 0x0a, - - 0x85, 0xbb, 0xad, 0xd1, 0x03, 0xd0, 0x08, 0xa5, - 0xe3, 0x29, 0xf0, 0x85, 0xbb, 0xa9, 0x06, 0x85, - - 0xc7, 0x58, 0x08, 0x78, 0x2c, 0x4f, 0x02, 0x10, - 0xdb, 0xa5, 0xea, 0x30, 0xd7, 0xa9, 0x01, 0x85, - - 0xea, 0x20, 0x46, 0xfb, 0x28, 0x60, 0xa9, 0x03, - 0xd0, 0x1b, 0xa9, 0x30, 0x85, 0xca, 0xd0, 0x13, - - 0xa9, 0x05, 0x8d, 0x10, 0xfe, 0xa2, 0xff, 0xca, - 0xd0, 0xfd, 0x86, 0xca, 0xa9, 0x85, 0x8d, 0x10, - - 0xfe, 0xa9, 0xd0, 0x05, 0xc6, 0x8d, 0x08, 0xfe, - 0x60, 0xae, 0xc6, 0x03, 0xac, 0xc7, 0x03, 0xe8, - - 0x86, 0xb4, 0xd0, 0x01, 0xc8, 0x84, 0xb5, 0x60, - 0xa0, 0x00, 0x84, 0xc0, 0x84, 0xbe, 0x84, 0xbf, - - 0x60, 0xa0, 0xff, 0xc8, 0xe8, 0xbd, 0x00, 0x03, - 0x99, 0xd2, 0x03, 0xd0, 0xf6, 0x60, 0xa0, 0x00, - - 0x58, 0xa2, 0x01, 0x84, 0xc3, 0xa9, 0x89, 0xa4, - 0xc3, 0x4c, 0xf4, 0xff, 0x85, 0xbc, 0x98, 0x4d, - - 0x47, 0x02, 0xa8, 0xa5, 0xe2, 0x25, 0xbc, 0x4a, - 0x88, 0xf0, 0x04, 0x4a, 0x88, 0xd0, 0x02, 0xb0, - - 0x4d, 0x00, 0xde, 0x43, 0x68, 0x61, 0x6e, 0x6e, - 0x65, 0x6c, 0x00, 0xa9, 0x01, 0x20, 0xd3, 0xfb, - - 0xf0, 0x3c, 0x8a, 0xa2, 0xb0, 0xa0, 0x00, 0x48, - 0xa9, 0xc0, 0x20, 0x06, 0x04, 0x90, 0xfb, 0x68, - - 0x4c, 0x06, 0x04, 0xaa, 0xa5, 0xb2, 0x25, 0xb3, - 0xc9, 0xff, 0xf0, 0x05, 0xad, 0x7a, 0x02, 0x29, - - 0x80, 0x60, 0xa9, 0x85, 0x8d, 0x10, 0xfe, 0x20, - 0x46, 0xfb, 0xa9, 0x10, 0x20, 0x63, 0xfb, 0x20, - - 0x95, 0xf9, 0xad, 0x08, 0xfe, 0x29, 0x02, 0xf0, - 0xf6, 0xa9, 0xaa, 0x8d, 0x09, 0xfe, 0x60, 0x00, - - 0x28, 0x43, 0x29, 0x20, 0x31, 0x39, 0x38, 0x31, - 0x20, 0x41, 0x63, 0x6f, 0x72, 0x6e, 0x20, 0x43, - - 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x72, 0x73, - 0x20, 0x4c, 0x74, 0x64, 0x2e, 0x54, 0x68, 0x61, - - 0x6e, 0x6b, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, - 0x64, 0x75, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x74, - - 0x68, 0x65, 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, - 0x77, 0x69, 0x6e, 0x67, 0x20, 0x63, 0x6f, 0x6e, - - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, - 0x73, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, - - 0x20, 0x64, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, - 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x66, 0x20, - - 0x74, 0x68, 0x65, 0x20, 0x42, 0x42, 0x43, 0x20, - 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x72, - - 0x20, 0x28, 0x61, 0x6d, 0x6f, 0x6e, 0x67, 0x20, - 0x6f, 0x74, 0x68, 0x65, 0x72, 0x73, 0x20, 0x74, - - 0x6f, 0x6f, 0x20, 0x6e, 0x75, 0x6d, 0x65, 0x72, - 0x6f, 0x75, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x6d, - - 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x3a, - 0x2d, 0x20, 0x44, 0x61, 0x76, 0x69, 0x64, 0x20, - - 0x41, 0x6c, 0x6c, 0x65, 0x6e, 0x2c, 0x42, 0x6f, - 0x62, 0x20, 0x41, 0x75, 0x73, 0x74, 0x69, 0x6e, - - 0x2c, 0x52, 0x61, 0x6d, 0x20, 0x42, 0x61, 0x6e, - 0x65, 0x72, 0x6a, 0x65, 0x65, 0x2c, 0x50, 0x61, - - 0x75, 0x6c, 0x20, 0x42, 0x6f, 0x6e, 0x64, 0x2c, - 0x41, 0x6c, 0x6c, 0x65, 0x6e, 0x20, 0x42, 0x6f, - - 0x6f, 0x74, 0x68, 0x72, 0x6f, 0x79, 0x64, 0x2c, - 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, - - 0x65, 0x2c, 0x43, 0x6c, 0x65, 0x61, 0x72, 0x74, - 0x6f, 0x6e, 0x65, 0x2c, 0x4a, 0x6f, 0x68, 0x6e, - - 0x20, 0x43, 0x6f, 0x6c, 0x6c, 0x2c, 0x4a, 0x6f, - 0x68, 0x6e, 0x20, 0x43, 0x6f, 0x78, 0x2c, 0x41, - - 0x6e, 0x64, 0x79, 0x20, 0x43, 0x72, 0x69, 0x70, - 0x70, 0x73, 0x2c, 0x43, 0x68, 0x72, 0x69, 0x73, - - 0x20, 0x43, 0x75, 0x72, 0x72, 0x79, 0x2c, 0x36, - 0x35, 0x30, 0x32, 0x20, 0x64, 0x65, 0x73, 0x69, - - 0x67, 0x6e, 0x65, 0x72, 0x73, 0x2c, 0x4a, 0x65, - 0x72, 0x65, 0x6d, 0x79, 0x20, 0x44, 0x69, 0x6f, - - 0x6e, 0x2c, 0x54, 0x69, 0x6d, 0x20, 0x44, 0x6f, - 0x62, 0x73, 0x6f, 0x6e, 0x2c, 0x4a, 0x6f, 0x65, - - 0x20, 0x44, 0x75, 0x6e, 0x6e, 0x2c, 0x50, 0x61, - 0x75, 0x6c, 0x20, 0x46, 0x61, 0x72, 0x72, 0x65, - - 0x6c, 0x6c, 0x2c, 0x46, 0x65, 0x72, 0x72, 0x61, - 0x6e, 0x74, 0x69, 0x2c, 0x53, 0x74, 0x65, 0x76, - - 0x65, 0x20, 0x46, 0x75, 0x72, 0x62, 0x65, 0x72, - 0x2c, 0x4a, 0x6f, 0x6e, 0x20, 0x47, 0x69, 0x62, - - 0x62, 0x6f, 0x6e, 0x73, 0x2c, 0x41, 0x6e, 0x64, - 0x72, 0x65, 0x77, 0x20, 0x47, 0x6f, 0x72, 0x64, - - 0x6f, 0x6e, 0x2c, 0x4c, 0x61, 0x77, 0x72, 0x65, - 0x6e, 0x63, 0x65, 0x20, 0x48, 0x61, 0x72, 0x64, - - 0x77, 0x69, 0x63, 0x6b, 0x2c, 0x44, 0x79, 0x6c, - 0x61, 0x6e, 0x20, 0x48, 0x61, 0x72, 0x72, 0x69, - - 0x73, 0x2c, 0x48, 0x65, 0x72, 0x6d, 0x61, 0x6e, - 0x6e, 0x20, 0x48, 0x61, 0x75, 0x73, 0x65, 0x72, - - 0x2c, 0x48, 0x69, 0x74, 0x61, 0x63, 0x68, 0x69, - 0x2c, 0x41, 0x6e, 0x64, 0x79, 0x20, 0x48, 0x6f, - - 0x70, 0x70, 0x65, 0x72, 0x2c, 0x49, 0x43, 0x4c, - 0x2c, 0x4d, 0x61, 0x72, 0x74, 0x69, 0x6e, 0x20, - - 0x4a, 0x61, 0x63, 0x6b, 0x73, 0x6f, 0x6e, 0x2c, - 0x42, 0x72, 0x69, 0x61, 0x6e, 0x20, 0x4a, 0x6f, - - 0x6e, 0x65, 0x73, 0x2c, 0x43, 0x68, 0x72, 0x69, - 0x73, 0x20, 0x4a, 0x6f, 0x72, 0x64, 0x61, 0x6e, - - 0x2c, 0x44, 0x61, 0x76, 0x69, 0x64, 0x20, 0x4b, - 0x69, 0x6e, 0x67, 0x2c, 0x44, 0x61, 0x76, 0x69, - - 0x64, 0x20, 0x4b, 0x69, 0x74, 0x73, 0x6f, 0x6e, - 0x2c, 0x50, 0x61, 0x75, 0x6c, 0x20, 0x4b, 0x72, - - 0x69, 0x77, 0x61, 0x63, 0x7a, 0x65, 0x6b, 0x2c, - 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x72, - - 0x20, 0x4c, 0x61, 0x62, 0x6f, 0x72, 0x61, 0x74, - 0x6f, 0x72, 0x79, 0x2c, 0x50, 0x65, 0x74, 0x65, - - 0x72, 0x20, 0x4d, 0x69, 0x6c, 0x6c, 0x65, 0x72, - 0x2c, 0x41, 0x72, 0x74, 0x68, 0x75, 0x72, 0x20, - - 0x4e, 0x6f, 0x72, 0x6d, 0x61, 0x6e, 0x2c, 0x47, - 0x6c, 0x79, 0x6e, 0x20, 0x50, 0x68, 0x69, 0x6c, - - 0x6c, 0x69, 0x70, 0x73, 0x2c, 0x4d, 0x69, 0x6b, - 0x65, 0x20, 0x50, 0x72, 0x65, 0x65, 0x73, 0x2c, - - 0x4a, 0x6f, 0x68, 0x6e, 0x20, 0x52, 0x61, 0x64, - 0x63, 0x6c, 0x69, 0x66, 0x66, 0x65, 0x2c, 0x57, - - 0x69, 0x6c, 0x62, 0x65, 0x72, 0x66, 0x6f, 0x72, - 0x63, 0x65, 0x20, 0x52, 0x6f, 0x61, 0x64, 0x2c, - - 0x50, 0x65, 0x74, 0x65, 0x72, 0x20, 0x52, 0x6f, - 0x62, 0x69, 0x6e, 0x73, 0x6f, 0x6e, 0x2c, 0x52, - - 0x69, 0x63, 0x68, 0x61, 0x72, 0x64, 0x20, 0x52, - 0x75, 0x73, 0x73, 0x65, 0x6c, 0x6c, 0x2c, 0x4b, - - 0x69, 0x6d, 0x20, 0x53, 0x70, 0x65, 0x6e, 0x63, - 0x65, 0x2d, 0x4a, 0x6f, 0x6e, 0x65, 0x73, 0x2c, - - 0x47, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20, 0x54, - 0x65, 0x62, 0x62, 0x79, 0x2c, 0x4a, 0x6f, 0x6e, - - 0x20, 0x54, 0x68, 0x61, 0x63, 0x6b, 0x72, 0x61, - 0x79, 0x2c, 0x43, 0x68, 0x72, 0x69, 0x73, 0x20, - - 0x54, 0x75, 0x72, 0x6e, 0x65, 0x72, 0x2c, 0x41, - 0x64, 0x72, 0x69, 0x61, 0x6e, 0x20, 0x57, 0x61, - - 0x72, 0x6e, 0x65, 0x72, 0x2c, 0x52, 0x6f, 0x67, - 0x65, 0x72, 0x20, 0x57, 0x69, 0x6c, 0x73, 0x6f, - - 0x6e, 0x2c, 0x41, 0x6c, 0x61, 0x6e, 0x20, 0x57, - 0x72, 0x69, 0x67, 0x68, 0x74, 0x2e, 0xcd, 0xd9, - - 0x20, 0x51, 0xff, 0x20, 0x51, 0xff, 0x20, 0x51, - 0xff, 0x20, 0x51, 0xff, 0x20, 0x51, 0xff, 0x20, - - 0x51, 0xff, 0x20, 0x51, 0xff, 0x20, 0x51, 0xff, - 0x20, 0x51, 0xff, 0x20, 0x51, 0xff, 0x20, 0x51, - - 0xff, 0x20, 0x51, 0xff, 0x20, 0x51, 0xff, 0x20, - 0x51, 0xff, 0x20, 0x51, 0xff, 0x20, 0x51, 0xff, - - 0x20, 0x51, 0xff, 0x20, 0x51, 0xff, 0x20, 0x51, - 0xff, 0x20, 0x51, 0xff, 0x20, 0x51, 0xff, 0x20, - - 0x51, 0xff, 0x20, 0x51, 0xff, 0x20, 0x51, 0xff, - 0x20, 0x51, 0xff, 0x20, 0x51, 0xff, 0x20, 0x51, - - 0xff, 0x48, 0x48, 0x48, 0x48, 0x48, 0x08, 0x48, - 0x8a, 0x48, 0x98, 0x48, 0xba, 0xa9, 0xff, 0x9d, - - 0x08, 0x01, 0xa9, 0x88, 0x9d, 0x07, 0x01, 0xbc, - 0x0a, 0x01, 0xb9, 0x9d, 0x0d, 0x9d, 0x05, 0x01, - - 0xb9, 0x9e, 0x0d, 0x9d, 0x06, 0x01, 0xa5, 0xf4, - 0x9d, 0x09, 0x01, 0xb9, 0x9f, 0x0d, 0x85, 0xf4, - - 0x8d, 0x30, 0xfe, 0x68, 0xa8, 0x68, 0xaa, 0x68, - 0x40, 0x08, 0x48, 0x8a, 0x48, 0xba, 0xbd, 0x02, - - 0x01, 0x9d, 0x05, 0x01, 0xbd, 0x03, 0x01, 0x9d, - 0x06, 0x01, 0x68, 0xaa, 0x68, 0x68, 0x68, 0x85, - - 0xf4, 0x8d, 0x30, 0xfe, 0x68, 0x28, 0x60, 0x8a, - 0xb0, 0x2a, 0xbc, 0x00, 0xfc, 0x60, 0xbc, 0x00, - - 0xfd, 0x60, 0xbc, 0x00, 0xfe, 0x60, 0x36, 0x40, - 0xd9, 0x4c, 0x0b, 0xdc, 0x4c, 0xc0, 0xc4, 0x4c, - - 0x94, 0xe4, 0x4c, 0x1e, 0xea, 0x4c, 0x2f, 0xea, - 0x4c, 0xc5, 0xde, 0x4c, 0xa4, 0xe0, 0x6c, 0x1c, - - 0x02, 0x6c, 0x1a, 0x02, 0x6c, 0x18, 0x02, 0x6c, - 0x16, 0x02, 0x6c, 0x14, 0x02, 0x6c, 0x12, 0x02, - - 0x6c, 0x10, 0x02, 0xc9, 0x0d, 0xd0, 0x07, 0xa9, - 0x0a, 0x20, 0xee, 0xff, 0xa9, 0x0d, 0x6c, 0x0e, - - 0x02, 0x6c, 0x0c, 0x02, 0x6c, 0x0a, 0x02, 0x6c, - 0x08, 0x02, 0x00, 0x0d, 0xcd, 0xd9, 0x1c, 0xdc - ] - -rom_basic2 = [ - 0xc9, 0x01, 0xf0, 0x1f, 0x60, 0xea, 0x60, 0x0e, - 0x01, 0x42, 0x41, 0x53, 0x49, 0x43, 0x00, 0x28, - - 0x43, 0x29, 0x31, 0x39, 0x38, 0x32, 0x20, 0x41, - 0x63, 0x6f, 0x72, 0x6e, 0x0a, 0x0d, 0x00, 0x00, - - 0x80, 0x00, 0x00, 0xa9, 0x84, 0x20, 0xf4, 0xff, - 0x86, 0x06, 0x84, 0x07, 0xa9, 0x83, 0x20, 0xf4, - - 0xff, 0x84, 0x18, 0xa2, 0x00, 0x86, 0x1f, 0x8e, - 0x02, 0x04, 0x8e, 0x03, 0x04, 0xca, 0x86, 0x23, - - 0xa2, 0x0a, 0x8e, 0x00, 0x04, 0xca, 0x8e, 0x01, - 0x04, 0xa9, 0x01, 0x25, 0x11, 0x05, 0x0d, 0x05, - - 0x0e, 0x05, 0x0f, 0x05, 0x10, 0xd0, 0x0c, 0xa9, - 0x41, 0x85, 0x0d, 0xa9, 0x52, 0x85, 0x0e, 0xa9, - - 0x57, 0x85, 0x0f, 0xa9, 0x02, 0x8d, 0x02, 0x02, - 0xa9, 0xb4, 0x8d, 0x03, 0x02, 0x58, 0x4c, 0xdd, - - 0x8a, 0x41, 0x4e, 0x44, 0x80, 0x00, 0x41, 0x42, - 0x53, 0x94, 0x00, 0x41, 0x43, 0x53, 0x95, 0x00, - - 0x41, 0x44, 0x56, 0x41, 0x4c, 0x96, 0x00, 0x41, - 0x53, 0x43, 0x97, 0x00, 0x41, 0x53, 0x4e, 0x98, - - 0x00, 0x41, 0x54, 0x4e, 0x99, 0x00, 0x41, 0x55, - 0x54, 0x4f, 0xc6, 0x10, 0x42, 0x47, 0x45, 0x54, - - 0x9a, 0x01, 0x42, 0x50, 0x55, 0x54, 0xd5, 0x03, - 0x43, 0x4f, 0x4c, 0x4f, 0x55, 0x52, 0xfb, 0x02, - - 0x43, 0x41, 0x4c, 0x4c, 0xd6, 0x02, 0x43, 0x48, - 0x41, 0x49, 0x4e, 0xd7, 0x02, 0x43, 0x48, 0x52, - - 0x24, 0xbd, 0x00, 0x43, 0x4c, 0x45, 0x41, 0x52, - 0xd8, 0x01, 0x43, 0x4c, 0x4f, 0x53, 0x45, 0xd9, - - 0x03, 0x43, 0x4c, 0x47, 0xda, 0x01, 0x43, 0x4c, - 0x53, 0xdb, 0x01, 0x43, 0x4f, 0x53, 0x9b, 0x00, - - 0x43, 0x4f, 0x55, 0x4e, 0x54, 0x9c, 0x01, 0x44, - 0x41, 0x54, 0x41, 0xdc, 0x20, 0x44, 0x45, 0x47, - - 0x9d, 0x00, 0x44, 0x45, 0x46, 0xdd, 0x00, 0x44, - 0x45, 0x4c, 0x45, 0x54, 0x45, 0xc7, 0x10, 0x44, - - 0x49, 0x56, 0x81, 0x00, 0x44, 0x49, 0x4d, 0xde, - 0x02, 0x44, 0x52, 0x41, 0x57, 0xdf, 0x02, 0x45, - - 0x4e, 0x44, 0x50, 0x52, 0x4f, 0x43, 0xe1, 0x01, - 0x45, 0x4e, 0x44, 0xe0, 0x01, 0x45, 0x4e, 0x56, - - 0x45, 0x4c, 0x4f, 0x50, 0x45, 0xe2, 0x02, 0x45, - 0x4c, 0x53, 0x45, 0x8b, 0x14, 0x45, 0x56, 0x41, - - 0x4c, 0xa0, 0x00, 0x45, 0x52, 0x4c, 0x9e, 0x01, - 0x45, 0x52, 0x52, 0x4f, 0x52, 0x85, 0x04, 0x45, - - 0x4f, 0x46, 0xc5, 0x01, 0x45, 0x4f, 0x52, 0x82, - 0x00, 0x45, 0x52, 0x52, 0x9f, 0x01, 0x45, 0x58, - - 0x50, 0xa1, 0x00, 0x45, 0x58, 0x54, 0xa2, 0x01, - 0x46, 0x4f, 0x52, 0xe3, 0x02, 0x46, 0x41, 0x4c, - - 0x53, 0x45, 0xa3, 0x01, 0x46, 0x4e, 0xa4, 0x08, - 0x47, 0x4f, 0x54, 0x4f, 0xe5, 0x12, 0x47, 0x45, - - 0x54, 0x24, 0xbe, 0x00, 0x47, 0x45, 0x54, 0xa5, - 0x00, 0x47, 0x4f, 0x53, 0x55, 0x42, 0xe4, 0x12, - - 0x47, 0x43, 0x4f, 0x4c, 0xe6, 0x02, 0x48, 0x49, - 0x4d, 0x45, 0x4d, 0x93, 0x43, 0x49, 0x4e, 0x50, - - 0x55, 0x54, 0xe8, 0x02, 0x49, 0x46, 0xe7, 0x02, - 0x49, 0x4e, 0x4b, 0x45, 0x59, 0x24, 0xbf, 0x00, - - 0x49, 0x4e, 0x4b, 0x45, 0x59, 0xa6, 0x00, 0x49, - 0x4e, 0x54, 0xa8, 0x00, 0x49, 0x4e, 0x53, 0x54, - - 0x52, 0x28, 0xa7, 0x00, 0x4c, 0x49, 0x53, 0x54, - 0xc9, 0x10, 0x4c, 0x49, 0x4e, 0x45, 0x86, 0x00, - - 0x4c, 0x4f, 0x41, 0x44, 0xc8, 0x02, 0x4c, 0x4f, - 0x4d, 0x45, 0x4d, 0x92, 0x43, 0x4c, 0x4f, 0x43, - - 0x41, 0x4c, 0xea, 0x02, 0x4c, 0x45, 0x46, 0x54, - 0x24, 0x28, 0xc0, 0x00, 0x4c, 0x45, 0x4e, 0xa9, - - 0x00, 0x4c, 0x45, 0x54, 0xe9, 0x04, 0x4c, 0x4f, - 0x47, 0xab, 0x00, 0x4c, 0x4e, 0xaa, 0x00, 0x4d, - - 0x49, 0x44, 0x24, 0x28, 0xc1, 0x00, 0x4d, 0x4f, - 0x44, 0x45, 0xeb, 0x02, 0x4d, 0x4f, 0x44, 0x83, - - 0x00, 0x4d, 0x4f, 0x56, 0x45, 0xec, 0x02, 0x4e, - 0x45, 0x58, 0x54, 0xed, 0x02, 0x4e, 0x45, 0x57, - - 0xca, 0x01, 0x4e, 0x4f, 0x54, 0xac, 0x00, 0x4f, - 0x4c, 0x44, 0xcb, 0x01, 0x4f, 0x4e, 0xee, 0x02, - - 0x4f, 0x46, 0x46, 0x87, 0x00, 0x4f, 0x52, 0x84, - 0x00, 0x4f, 0x50, 0x45, 0x4e, 0x49, 0x4e, 0x8e, - - 0x00, 0x4f, 0x50, 0x45, 0x4e, 0x4f, 0x55, 0x54, - 0xae, 0x00, 0x4f, 0x50, 0x45, 0x4e, 0x55, 0x50, - - 0xad, 0x00, 0x4f, 0x53, 0x43, 0x4c, 0x49, 0xff, - 0x02, 0x50, 0x52, 0x49, 0x4e, 0x54, 0xf1, 0x02, - - 0x50, 0x41, 0x47, 0x45, 0x90, 0x43, 0x50, 0x54, - 0x52, 0x8f, 0x43, 0x50, 0x49, 0xaf, 0x01, 0x50, - - 0x4c, 0x4f, 0x54, 0xf0, 0x02, 0x50, 0x4f, 0x49, - 0x4e, 0x54, 0x28, 0xb0, 0x00, 0x50, 0x52, 0x4f, - - 0x43, 0xf2, 0x0a, 0x50, 0x4f, 0x53, 0xb1, 0x01, - 0x52, 0x45, 0x54, 0x55, 0x52, 0x4e, 0xf8, 0x01, - - 0x52, 0x45, 0x50, 0x45, 0x41, 0x54, 0xf5, 0x00, - 0x52, 0x45, 0x50, 0x4f, 0x52, 0x54, 0xf6, 0x01, - - 0x52, 0x45, 0x41, 0x44, 0xf3, 0x02, 0x52, 0x45, - 0x4d, 0xf4, 0x20, 0x52, 0x55, 0x4e, 0xf9, 0x01, - - 0x52, 0x41, 0x44, 0xb2, 0x00, 0x52, 0x45, 0x53, - 0x54, 0x4f, 0x52, 0x45, 0xf7, 0x12, 0x52, 0x49, - - 0x47, 0x48, 0x54, 0x24, 0x28, 0xc2, 0x00, 0x52, - 0x4e, 0x44, 0xb3, 0x01, 0x52, 0x45, 0x4e, 0x55, - - 0x4d, 0x42, 0x45, 0x52, 0xcc, 0x10, 0x53, 0x54, - 0x45, 0x50, 0x88, 0x00, 0x53, 0x41, 0x56, 0x45, - - 0xcd, 0x02, 0x53, 0x47, 0x4e, 0xb4, 0x00, 0x53, - 0x49, 0x4e, 0xb5, 0x00, 0x53, 0x51, 0x52, 0xb6, - - 0x00, 0x53, 0x50, 0x43, 0x89, 0x00, 0x53, 0x54, - 0x52, 0x24, 0xc3, 0x00, 0x53, 0x54, 0x52, 0x49, - - 0x4e, 0x47, 0x24, 0x28, 0xc4, 0x00, 0x53, 0x4f, - 0x55, 0x4e, 0x44, 0xd4, 0x02, 0x53, 0x54, 0x4f, - - 0x50, 0xfa, 0x01, 0x54, 0x41, 0x4e, 0xb7, 0x00, - 0x54, 0x48, 0x45, 0x4e, 0x8c, 0x14, 0x54, 0x4f, - - 0xb8, 0x00, 0x54, 0x41, 0x42, 0x28, 0x8a, 0x00, - 0x54, 0x52, 0x41, 0x43, 0x45, 0xfc, 0x12, 0x54, - - 0x49, 0x4d, 0x45, 0x91, 0x43, 0x54, 0x52, 0x55, - 0x45, 0xb9, 0x01, 0x55, 0x4e, 0x54, 0x49, 0x4c, - - 0xfd, 0x02, 0x55, 0x53, 0x52, 0xba, 0x00, 0x56, - 0x44, 0x55, 0xef, 0x02, 0x56, 0x41, 0x4c, 0xbb, - - 0x00, 0x56, 0x50, 0x4f, 0x53, 0xbc, 0x01, 0x57, - 0x49, 0x44, 0x54, 0x48, 0xfe, 0x02, 0x50, 0x41, - - 0x47, 0x45, 0xd0, 0x00, 0x50, 0x54, 0x52, 0xcf, - 0x00, 0x54, 0x49, 0x4d, 0x45, 0xd1, 0x00, 0x4c, - - 0x4f, 0x4d, 0x45, 0x4d, 0xd2, 0x00, 0x48, 0x49, - 0x4d, 0x45, 0x4d, 0xd3, 0x00, 0x78, 0x47, 0xc0, - - 0xb4, 0xfc, 0x03, 0x6a, 0xd4, 0x33, 0x9e, 0xda, - 0x07, 0x6f, 0x8d, 0xf7, 0xc2, 0x9f, 0xa6, 0xe9, - - 0x91, 0x46, 0xca, 0x95, 0xb9, 0xad, 0xe2, 0x78, - 0xd1, 0xfe, 0xa8, 0xd1, 0x80, 0x7c, 0xcb, 0x41, - - 0x6d, 0xb1, 0x49, 0x88, 0x98, 0xb4, 0xbe, 0xdc, - 0xc4, 0xd2, 0x2f, 0x76, 0xbd, 0xbf, 0x26, 0xcc, - - 0x39, 0xee, 0x94, 0xc2, 0xb8, 0xac, 0x31, 0x24, - 0x9c, 0xda, 0xb6, 0xa3, 0xf3, 0x2a, 0x30, 0x83, - - 0xc9, 0x6f, 0x5d, 0x4c, 0x58, 0xd2, 0x2a, 0x8d, - 0x99, 0xbd, 0xc4, 0x7d, 0x7d, 0x2f, 0xe8, 0xc8, - - 0x56, 0x72, 0xc4, 0x88, 0xcc, 0x7a, 0xc2, 0x44, - 0xe4, 0x23, 0x9a, 0xe4, 0x95, 0x15, 0x2f, 0xf1, - - 0x9a, 0x04, 0x1f, 0x7d, 0xe4, 0xe4, 0xe6, 0xb6, - 0x11, 0xd0, 0x8e, 0x95, 0xb1, 0xa0, 0xc2, 0xbf, - - 0xbf, 0xae, 0xae, 0xae, 0xaf, 0xad, 0xa8, 0xab, - 0xac, 0xa8, 0xa9, 0xbf, 0xa9, 0xae, 0xab, 0xaf, - - 0xaf, 0xab, 0xaa, 0xbf, 0xae, 0xb1, 0xaf, 0xac, - 0xac, 0xac, 0xae, 0xa7, 0xab, 0xac, 0xbf, 0xbf, - - 0xab, 0xab, 0xab, 0xab, 0xaf, 0xab, 0xa9, 0xa7, - 0xa6, 0xae, 0xac, 0xab, 0xac, 0xab, 0xb3, 0xaf, - - 0xb0, 0xaf, 0xb0, 0xaf, 0xb0, 0xb0, 0xac, 0x90, - 0x8f, 0xbf, 0xb5, 0x8a, 0x8a, 0x8f, 0xbe, 0x98, - - 0xbf, 0x92, 0x92, 0x92, 0x92, 0xb4, 0xbf, 0x8e, - 0xbf, 0x92, 0xbf, 0x8e, 0x8e, 0x8b, 0x8b, 0x91, - - 0x93, 0x8a, 0x93, 0xb4, 0xb7, 0xb8, 0xb8, 0x93, - 0x98, 0xba, 0x8b, 0x93, 0x93, 0x93, 0xb6, 0xb9, - - 0x94, 0x93, 0x8d, 0x93, 0xbb, 0x8b, 0xbb, 0xbf, - 0xba, 0xb8, 0xbd, 0x8a, 0x93, 0x92, 0xbb, 0xb4, - - 0xbe, 0x4b, 0x83, 0x84, 0x89, 0x96, 0xb8, 0xb9, - 0xd8, 0xd9, 0xf0, 0x01, 0x10, 0x81, 0x90, 0x89, - - 0x93, 0xa3, 0xa4, 0xa9, 0x38, 0x39, 0x78, 0x01, - 0x13, 0x21, 0x63, 0x73, 0xb1, 0xa9, 0xc5, 0x0c, - - 0xc3, 0xd3, 0xc4, 0xf2, 0x41, 0x83, 0xb0, 0x81, - 0x43, 0x6c, 0x72, 0xec, 0xf2, 0xa3, 0xc3, 0x18, - - 0x19, 0x34, 0xb0, 0x72, 0x98, 0x99, 0x81, 0x98, - 0x99, 0x14, 0x35, 0x0a, 0x0d, 0x0d, 0x0d, 0x0d, - - 0x10, 0x10, 0x25, 0x25, 0x39, 0x41, 0x41, 0x41, - 0x41, 0x4a, 0x4a, 0x4c, 0x4c, 0x4c, 0x50, 0x50, - - 0x52, 0x53, 0x53, 0x53, 0x08, 0x08, 0x08, 0x09, - 0x09, 0x0a, 0x0a, 0x0a, 0x05, 0x15, 0x3e, 0x04, - - 0x0d, 0x30, 0x4c, 0x06, 0x32, 0x49, 0x49, 0x10, - 0x25, 0x0e, 0x0e, 0x09, 0x29, 0x2a, 0x30, 0x30, - - 0x4e, 0x4e, 0x4e, 0x3e, 0x16, 0x00, 0x18, 0xd8, - 0x58, 0xb8, 0xca, 0x88, 0xe8, 0xc8, 0xea, 0x48, - - 0x08, 0x68, 0x28, 0x40, 0x60, 0x38, 0xf8, 0x78, - 0xaa, 0xa8, 0xba, 0x8a, 0x9a, 0x98, 0x90, 0xb0, - - 0xf0, 0x30, 0xd0, 0x10, 0x50, 0x70, 0x21, 0x41, - 0x01, 0x61, 0xc1, 0xa1, 0xe1, 0x06, 0x46, 0x26, - - 0x66, 0xc6, 0xe6, 0xe0, 0xc0, 0x20, 0x4c, 0x20, - 0xa2, 0xa0, 0x81, 0x86, 0x84, 0xa9, 0xff, 0x85, - - 0x28, 0x4c, 0xa3, 0x8b, 0xa9, 0x03, 0x85, 0x28, - 0x20, 0x97, 0x8a, 0xc9, 0x5d, 0xf0, 0xee, 0x20, - - 0x6d, 0x98, 0xc6, 0x0a, 0x20, 0xba, 0x85, 0xc6, - 0x0a, 0xa5, 0x28, 0x4a, 0x90, 0x60, 0xa5, 0x1e, - - 0x69, 0x04, 0x85, 0x3f, 0xa5, 0x38, 0x20, 0x45, - 0xb5, 0xa5, 0x37, 0x20, 0x62, 0xb5, 0xa2, 0xfc, - - 0xa4, 0x39, 0x10, 0x02, 0xa4, 0x36, 0x84, 0x38, - 0xf0, 0x1c, 0xa0, 0x00, 0xe8, 0xd0, 0x0d, 0x20, - - 0x25, 0xbc, 0xa6, 0x3f, 0x20, 0x65, 0xb5, 0xca, - 0xd0, 0xfa, 0xa2, 0xfd, 0xb1, 0x3a, 0x20, 0x62, - - 0xb5, 0xc8, 0xc6, 0x38, 0xd0, 0xe6, 0xe8, 0x10, - 0x0c, 0x20, 0x65, 0xb5, 0x20, 0x58, 0xb5, 0x20, - - 0x58, 0xb5, 0x4c, 0x56, 0x85, 0xa0, 0x00, 0xb1, - 0x0b, 0xc9, 0x3a, 0xf0, 0x0a, 0xc9, 0x0d, 0xf0, - - 0x0a, 0x20, 0x0e, 0xb5, 0xc8, 0xd0, 0xf0, 0xc4, - 0x0a, 0x90, 0xf6, 0x20, 0x25, 0xbc, 0xa4, 0x0a, - - 0x88, 0xc8, 0xb1, 0x0b, 0xc9, 0x3a, 0xf0, 0x04, - 0xc9, 0x0d, 0xd0, 0xf5, 0x20, 0x59, 0x98, 0x88, - - 0xb1, 0x0b, 0xc9, 0x3a, 0xf0, 0x0c, 0xa5, 0x0c, - 0xc9, 0x07, 0xd0, 0x03, 0x4c, 0xf6, 0x8a, 0x20, - - 0x90, 0x98, 0x4c, 0x08, 0x85, 0x20, 0x82, 0x95, - 0xf0, 0x5a, 0xb0, 0x58, 0x20, 0x94, 0xbd, 0x20, - - 0x3a, 0xae, 0x85, 0x27, 0x20, 0xb4, 0xb4, 0x20, - 0x27, 0x88, 0xa2, 0x03, 0x20, 0x97, 0x8a, 0xa0, - - 0x00, 0x84, 0x3d, 0xc9, 0x3a, 0xf0, 0x64, 0xc9, - 0x0d, 0xf0, 0x60, 0xc9, 0x5c, 0xf0, 0x5c, 0xc9, - - 0x2e, 0xf0, 0xd2, 0xc6, 0x0a, 0xa4, 0x0a, 0xe6, - 0x0a, 0xb1, 0x0b, 0x30, 0x2a, 0xc9, 0x20, 0xf0, - - 0x10, 0xa0, 0x05, 0x0a, 0x0a, 0x0a, 0x0a, 0x26, - 0x3d, 0x26, 0x3e, 0x88, 0xd0, 0xf8, 0xca, 0xd0, - - 0xe4, 0xa2, 0x3a, 0xa5, 0x3d, 0xdd, 0x50, 0x84, - 0xd0, 0x07, 0xbc, 0x8a, 0x84, 0xc4, 0x3e, 0xf0, - - 0x1f, 0xca, 0xd0, 0xf1, 0x4c, 0x2a, 0x98, 0xa2, - 0x22, 0xc9, 0x80, 0xf0, 0x13, 0xe8, 0xc9, 0x82, - - 0xf0, 0x0e, 0xe8, 0xc9, 0x84, 0xd0, 0xed, 0xe6, - 0x0a, 0xc8, 0xb1, 0x0b, 0xc9, 0x41, 0xd0, 0xe4, - - 0xbd, 0xc4, 0x84, 0x85, 0x29, 0xa0, 0x01, 0xe0, - 0x1a, 0xb0, 0x48, 0xad, 0x40, 0x04, 0x85, 0x37, - - 0x84, 0x39, 0xa6, 0x28, 0xe0, 0x04, 0xae, 0x41, - 0x04, 0x86, 0x38, 0x90, 0x06, 0xad, 0x3c, 0x04, - - 0xae, 0x3d, 0x04, 0x85, 0x3a, 0x86, 0x3b, 0x98, - 0xf0, 0x28, 0x10, 0x04, 0xa4, 0x36, 0xf0, 0x22, - - 0x88, 0xb9, 0x29, 0x00, 0x24, 0x39, 0x10, 0x03, - 0xb9, 0x00, 0x06, 0x91, 0x3a, 0xee, 0x40, 0x04, - - 0xd0, 0x03, 0xee, 0x41, 0x04, 0x90, 0x08, 0xee, - 0x3c, 0x04, 0xd0, 0x03, 0xee, 0x3d, 0x04, 0x98, - - 0xd0, 0xde, 0x60, 0xe0, 0x22, 0xb0, 0x40, 0x20, - 0x21, 0x88, 0x18, 0xa5, 0x2a, 0xed, 0x40, 0x04, - - 0xa8, 0xa5, 0x2b, 0xed, 0x41, 0x04, 0xc0, 0x01, - 0x88, 0xe9, 0x00, 0xf0, 0x25, 0xc9, 0xff, 0xf0, - - 0x1c, 0xa5, 0x28, 0x4a, 0xf0, 0x0f, 0x00, 0x01, - 0x4f, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x72, - - 0x61, 0x6e, 0x67, 0x65, 0x00, 0xa8, 0x84, 0x2a, - 0xa0, 0x02, 0x4c, 0x2b, 0x86, 0x98, 0x30, 0xf6, - - 0x10, 0xdf, 0x98, 0x10, 0xf1, 0x30, 0xda, 0xe0, - 0x29, 0xb0, 0x18, 0x20, 0x97, 0x8a, 0xc9, 0x23, - - 0xd0, 0x18, 0x20, 0x2f, 0x88, 0x20, 0x21, 0x88, - 0xa5, 0x2b, 0xf0, 0xdc, 0x00, 0x02, 0x42, 0x79, - - 0x74, 0x65, 0x00, 0xe0, 0x36, 0xd0, 0x68, 0x20, - 0x97, 0x8a, 0xc9, 0x28, 0xd0, 0x37, 0x20, 0x21, - - 0x88, 0x20, 0x97, 0x8a, 0xc9, 0x29, 0xd0, 0x13, - 0x20, 0x97, 0x8a, 0xc9, 0x2c, 0xd0, 0x1e, 0x20, - - 0x2c, 0x88, 0x20, 0x97, 0x8a, 0xc9, 0x59, 0xd0, - 0x14, 0xf0, 0xcd, 0xc9, 0x2c, 0xd0, 0x0e, 0x20, - - 0x97, 0x8a, 0xc9, 0x58, 0xd0, 0x07, 0x20, 0x97, - 0x8a, 0xc9, 0x29, 0xf0, 0xbb, 0x00, 0x03, 0x49, - - 0x6e, 0x64, 0x65, 0x78, 0x00, 0xc6, 0x0a, 0x20, - 0x21, 0x88, 0x20, 0x97, 0x8a, 0xc9, 0x2c, 0xd0, - - 0x14, 0x20, 0x2c, 0x88, 0x20, 0x97, 0x8a, 0xc9, - 0x58, 0xf0, 0x0a, 0xc9, 0x59, 0xd0, 0xde, 0x20, - - 0x2f, 0x88, 0x4c, 0x9a, 0x87, 0x20, 0x32, 0x88, - 0xa5, 0x2b, 0xd0, 0xf3, 0x4c, 0xa8, 0x86, 0xe0, - - 0x2f, 0xb0, 0x2b, 0xe0, 0x2d, 0xb0, 0x09, 0x20, - 0x97, 0x8a, 0xc9, 0x41, 0xf0, 0x19, 0xc6, 0x0a, - - 0x20, 0x21, 0x88, 0x20, 0x97, 0x8a, 0xc9, 0x2c, - 0xd0, 0xde, 0x20, 0x2c, 0x88, 0x20, 0x97, 0x8a, - - 0xc9, 0x58, 0xf0, 0xd4, 0x4c, 0x0d, 0x87, 0x20, - 0x32, 0x88, 0xa0, 0x01, 0xd0, 0x2e, 0xe0, 0x32, - - 0xb0, 0x16, 0xe0, 0x31, 0xf0, 0x0c, 0x20, 0x97, - 0x8a, 0xc9, 0x23, 0xd0, 0x03, 0x4c, 0xc5, 0x86, - - 0xc6, 0x0a, 0x20, 0x21, 0x88, 0x4c, 0x35, 0x87, - 0xe0, 0x33, 0xf0, 0x0b, 0xb0, 0x24, 0x20, 0x97, - - 0x8a, 0xc9, 0x28, 0xf0, 0x0a, 0xc6, 0x0a, 0x20, - 0x21, 0x88, 0xa0, 0x03, 0x4c, 0x2b, 0x86, 0x20, - - 0x2c, 0x88, 0x20, 0x2c, 0x88, 0x20, 0x21, 0x88, - 0x20, 0x97, 0x8a, 0xc9, 0x29, 0xf0, 0xeb, 0x4c, - - 0x0d, 0x87, 0xe0, 0x39, 0xb0, 0x5d, 0xa5, 0x3d, - 0x49, 0x01, 0x29, 0x1f, 0x48, 0xe0, 0x37, 0xb0, - - 0x2f, 0x20, 0x97, 0x8a, 0xc9, 0x23, 0xd0, 0x04, - 0x68, 0x4c, 0xc5, 0x86, 0xc6, 0x0a, 0x20, 0x21, - - 0x88, 0x68, 0x85, 0x37, 0x20, 0x97, 0x8a, 0xc9, - 0x2c, 0xf0, 0x03, 0x4c, 0x35, 0x87, 0x20, 0x97, - - 0x8a, 0x29, 0x1f, 0xc5, 0x37, 0xd0, 0x06, 0x20, - 0x2c, 0x88, 0x4c, 0x35, 0x87, 0x4c, 0x0d, 0x87, - - 0x20, 0x21, 0x88, 0x68, 0x85, 0x37, 0x20, 0x97, - 0x8a, 0xc9, 0x2c, 0xd0, 0x13, 0x20, 0x97, 0x8a, - - 0x29, 0x1f, 0xc5, 0x37, 0xd0, 0xe7, 0x20, 0x2c, - 0x88, 0xa5, 0x2b, 0xf0, 0x03, 0x4c, 0xcc, 0x86, - - 0x4c, 0x38, 0x87, 0xd0, 0x25, 0x20, 0x21, 0x88, - 0xa5, 0x2a, 0x85, 0x28, 0xa0, 0x00, 0x4c, 0x2b, - - 0x86, 0x20, 0x1d, 0x9b, 0x20, 0xf0, 0x92, 0xa4, - 0x1b, 0x84, 0x0a, 0x60, 0x20, 0x2f, 0x88, 0x20, - - 0x32, 0x88, 0xa5, 0x29, 0x18, 0x69, 0x04, 0x85, - 0x29, 0x60, 0xa2, 0x01, 0xa4, 0x0a, 0xe6, 0x0a, - - 0xb1, 0x0b, 0xc9, 0x42, 0xf0, 0x12, 0xe8, 0xc9, - 0x57, 0xf0, 0x0d, 0xa2, 0x04, 0xc9, 0x44, 0xf0, - - 0x07, 0xc9, 0x53, 0xf0, 0x15, 0x4c, 0x2a, 0x98, - 0x8a, 0x48, 0x20, 0x21, 0x88, 0xa2, 0x29, 0x20, - - 0x44, 0xbe, 0x68, 0xa8, 0x4c, 0x2b, 0x86, 0x4c, - 0x0e, 0x8c, 0xa5, 0x28, 0x48, 0x20, 0x1d, 0x9b, - - 0xd0, 0xf5, 0x68, 0x85, 0x28, 0x20, 0x27, 0x88, - 0xa0, 0xff, 0xd0, 0xe8, 0x48, 0x18, 0x98, 0x65, - - 0x37, 0x85, 0x39, 0xa0, 0x00, 0x98, 0x65, 0x38, - 0x85, 0x3a, 0x68, 0x91, 0x37, 0xc8, 0xb1, 0x39, - - 0x91, 0x37, 0xc9, 0x0d, 0xd0, 0xf7, 0x60, 0x29, - 0x0f, 0x85, 0x3d, 0x84, 0x3e, 0xc8, 0xb1, 0x37, - - 0xc9, 0x3a, 0xb0, 0x36, 0xc9, 0x30, 0x90, 0x32, - 0x29, 0x0f, 0x48, 0xa6, 0x3e, 0xa5, 0x3d, 0x0a, - - 0x26, 0x3e, 0x30, 0x21, 0x0a, 0x26, 0x3e, 0x30, - 0x1c, 0x65, 0x3d, 0x85, 0x3d, 0x8a, 0x65, 0x3e, - - 0x06, 0x3d, 0x2a, 0x30, 0x10, 0xb0, 0x0e, 0x85, - 0x3e, 0x68, 0x65, 0x3d, 0x85, 0x3d, 0x90, 0xcd, - - 0xe6, 0x3e, 0x10, 0xc9, 0x48, 0x68, 0xa0, 0x00, - 0x38, 0x60, 0x88, 0xa9, 0x8d, 0x20, 0x7c, 0x88, - - 0xa5, 0x37, 0x69, 0x02, 0x85, 0x39, 0xa5, 0x38, - 0x69, 0x00, 0x85, 0x3a, 0xb1, 0x37, 0x91, 0x39, - - 0x88, 0xd0, 0xf9, 0xa0, 0x03, 0xa5, 0x3e, 0x09, - 0x40, 0x91, 0x37, 0x88, 0xa5, 0x3d, 0x29, 0x3f, - - 0x09, 0x40, 0x91, 0x37, 0x88, 0xa5, 0x3d, 0x29, - 0xc0, 0x85, 0x3d, 0xa5, 0x3e, 0x29, 0xc0, 0x4a, - - 0x4a, 0x05, 0x3d, 0x4a, 0x4a, 0x49, 0x54, 0x91, - 0x37, 0x20, 0x44, 0x89, 0x20, 0x44, 0x89, 0x20, - - 0x44, 0x89, 0xa0, 0x00, 0x18, 0x60, 0xc9, 0x7b, - 0xb0, 0xfa, 0xc9, 0x5f, 0xb0, 0x0e, 0xc9, 0x5b, - - 0xb0, 0xf2, 0xc9, 0x41, 0xb0, 0x06, 0xc9, 0x3a, - 0xb0, 0xea, 0xc9, 0x30, 0x60, 0xc9, 0x2e, 0xd0, - - 0xf5, 0x60, 0xb1, 0x37, 0xe6, 0x37, 0xd0, 0x02, - 0xe6, 0x38, 0x60, 0x20, 0x44, 0x89, 0xb1, 0x37, - - 0x60, 0xa0, 0x00, 0x84, 0x3b, 0x84, 0x3c, 0xb1, - 0x37, 0xc9, 0x0d, 0xf0, 0xed, 0xc9, 0x20, 0xd0, - - 0x05, 0x20, 0x44, 0x89, 0xd0, 0xf1, 0xc9, 0x26, - 0xd0, 0x12, 0x20, 0x4b, 0x89, 0x20, 0x36, 0x89, - - 0xb0, 0xf8, 0xc9, 0x41, 0x90, 0xe1, 0xc9, 0x47, - 0x90, 0xf0, 0xb0, 0xdb, 0xc9, 0x22, 0xd0, 0x0c, - - 0x20, 0x4b, 0x89, 0xc9, 0x22, 0xf0, 0xda, 0xc9, - 0x0d, 0xd0, 0xf5, 0x60, 0xc9, 0x3a, 0xd0, 0x06, - - 0x84, 0x3b, 0x84, 0x3c, 0xf0, 0xcb, 0xc9, 0x2c, - 0xf0, 0xc7, 0xc9, 0x2a, 0xd0, 0x05, 0xa5, 0x3b, - - 0xd0, 0x41, 0x60, 0xc9, 0x2e, 0xf0, 0x0e, 0x20, - 0x36, 0x89, 0x90, 0x33, 0xa6, 0x3c, 0xf0, 0x05, - - 0x20, 0x97, 0x88, 0x90, 0x34, 0xb1, 0x37, 0x20, - 0x3d, 0x89, 0x90, 0x06, 0x20, 0x44, 0x89, 0x4c, - - 0xb5, 0x89, 0xa2, 0xff, 0x86, 0x3b, 0x84, 0x3c, - 0x4c, 0x57, 0x89, 0x20, 0x26, 0x89, 0x90, 0x13, - - 0xa0, 0x00, 0xb1, 0x37, 0x20, 0x26, 0x89, 0x90, - 0xe9, 0x20, 0x44, 0x89, 0x4c, 0xd2, 0x89, 0xc9, - - 0x41, 0xb0, 0x09, 0xa2, 0xff, 0x86, 0x3b, 0x84, - 0x3c, 0x4c, 0x61, 0x89, 0xc9, 0x58, 0xb0, 0xdb, - - 0xa2, 0x71, 0x86, 0x39, 0xa2, 0x80, 0x86, 0x3a, - 0xd1, 0x39, 0x90, 0xd6, 0xd0, 0x0f, 0xc8, 0xb1, - - 0x39, 0x30, 0x34, 0xd1, 0x37, 0xf0, 0xf7, 0xb1, - 0x37, 0xc9, 0x2e, 0xf0, 0x0b, 0xc8, 0xb1, 0x39, - - 0x10, 0xfb, 0xc9, 0xfe, 0xd0, 0x0f, 0xb0, 0xb8, - 0xc8, 0xb1, 0x39, 0x30, 0x1a, 0xe6, 0x39, 0xd0, - - 0xf8, 0xe6, 0x3a, 0xd0, 0xf4, 0x38, 0xc8, 0x98, - 0x65, 0x39, 0x85, 0x39, 0x90, 0x02, 0xe6, 0x3a, - - 0xa0, 0x00, 0xb1, 0x37, 0x4c, 0xf8, 0x89, 0xaa, - 0xc8, 0xb1, 0x39, 0x85, 0x3d, 0x88, 0x4a, 0x90, - - 0x07, 0xb1, 0x37, 0x20, 0x26, 0x89, 0xb0, 0x88, - 0x8a, 0x24, 0x3d, 0x50, 0x07, 0xa6, 0x3b, 0xd0, - - 0x03, 0x18, 0x69, 0x40, 0x88, 0x20, 0x7c, 0x88, - 0xa0, 0x00, 0xa2, 0xff, 0xa5, 0x3d, 0x4a, 0x4a, - - 0x90, 0x04, 0x86, 0x3b, 0x84, 0x3c, 0x4a, 0x90, - 0x04, 0x84, 0x3b, 0x84, 0x3c, 0x4a, 0x90, 0x11, - - 0x48, 0xc8, 0xb1, 0x37, 0x20, 0x26, 0x89, 0x90, - 0x06, 0x20, 0x44, 0x89, 0x4c, 0x72, 0x8a, 0x88, - - 0x68, 0x4a, 0x90, 0x02, 0x86, 0x3c, 0x4a, 0xb0, - 0x0d, 0x4c, 0x61, 0x89, 0xa4, 0x1b, 0xe6, 0x1b, - - 0xb1, 0x19, 0xc9, 0x20, 0xf0, 0xf6, 0x60, 0xa4, - 0x0a, 0xe6, 0x0a, 0xb1, 0x0b, 0xc9, 0x20, 0xf0, - - 0xf6, 0x60, 0x00, 0x05, 0x4d, 0x69, 0x73, 0x73, - 0x69, 0x6e, 0x67, 0x20, 0x2c, 0x00, 0x20, 0x8c, - - 0x8a, 0xc9, 0x2c, 0xd0, 0xed, 0x60, 0x20, 0x57, - 0x98, 0xa5, 0x18, 0x85, 0x38, 0xa9, 0x00, 0x85, - - 0x37, 0x91, 0x37, 0x20, 0x6f, 0xbe, 0xd0, 0x2b, - 0x20, 0x57, 0x98, 0x20, 0x6f, 0xbe, 0xd0, 0x26, - - 0x20, 0x57, 0x98, 0x00, 0x00, 0x53, 0x54, 0x4f, - 0x50, 0x00, 0x20, 0x57, 0x98, 0xa9, 0x0d, 0xa4, - - 0x18, 0x84, 0x13, 0xa0, 0x00, 0x84, 0x12, 0x84, - 0x20, 0x91, 0x12, 0xa9, 0xff, 0xc8, 0x91, 0x12, - - 0xc8, 0x84, 0x12, 0x20, 0x20, 0xbd, 0xa0, 0x07, - 0x84, 0x0c, 0xa0, 0x00, 0x84, 0x0b, 0xa9, 0x33, - - 0x85, 0x16, 0xa9, 0xb4, 0x85, 0x17, 0xa9, 0x3e, - 0x20, 0x02, 0xbc, 0xa9, 0x33, 0x85, 0x16, 0xa9, - - 0xb4, 0x85, 0x17, 0xa2, 0xff, 0x86, 0x28, 0x86, - 0x3c, 0x9a, 0x20, 0x3a, 0xbd, 0xa8, 0xa5, 0x0b, - - 0x85, 0x37, 0xa5, 0x0c, 0x85, 0x38, 0x84, 0x3b, - 0x84, 0x0a, 0x20, 0x57, 0x89, 0x20, 0xdf, 0x97, - - 0x90, 0x06, 0x20, 0x8d, 0xbc, 0x4c, 0xf3, 0x8a, - 0x20, 0x97, 0x8a, 0xc9, 0xc6, 0xb0, 0x72, 0x90, - - 0x7e, 0x4c, 0xf6, 0x8a, 0x4c, 0x04, 0x85, 0xba, - 0xe0, 0xfc, 0xb0, 0x0d, 0xad, 0xff, 0x01, 0xc9, - - 0xa4, 0xd0, 0x06, 0x20, 0x1d, 0x9b, 0x4c, 0x4c, - 0x98, 0x00, 0x07, 0x4e, 0x6f, 0x20, 0xa4, 0x00, - - 0xa4, 0x0a, 0x88, 0xb1, 0x0b, 0xc9, 0x3d, 0xf0, - 0xde, 0xc9, 0x2a, 0xf0, 0x06, 0xc9, 0x5b, 0xf0, - - 0xd3, 0xd0, 0x23, 0x20, 0x6d, 0x98, 0xa6, 0x0b, - 0xa4, 0x0c, 0x20, 0xf7, 0xff, 0xa9, 0x0d, 0xa4, - - 0x0a, 0x88, 0xc8, 0xd1, 0x0b, 0xd0, 0xfb, 0xc9, - 0x8b, 0xf0, 0xf2, 0xa5, 0x0c, 0xc9, 0x07, 0xf0, - - 0xb0, 0x20, 0x90, 0x98, 0xd0, 0x0d, 0xc6, 0x0a, - 0x20, 0x57, 0x98, 0xa0, 0x00, 0xb1, 0x0b, 0xc9, - - 0x3a, 0xd0, 0xe4, 0xa4, 0x0a, 0xe6, 0x0a, 0xb1, - 0x0b, 0xc9, 0x20, 0xf0, 0xf6, 0xc9, 0xcf, 0x90, - - 0x0e, 0xaa, 0xbd, 0xdf, 0x82, 0x85, 0x37, 0xbd, - 0x51, 0x83, 0x85, 0x38, 0x6c, 0x37, 0x00, 0xa6, - - 0x0b, 0x86, 0x19, 0xa6, 0x0c, 0x86, 0x1a, 0x84, - 0x1b, 0x20, 0xdd, 0x95, 0xd0, 0x1b, 0xb0, 0x90, - - 0x86, 0x1b, 0x20, 0x41, 0x98, 0x20, 0xfc, 0x94, - 0xa2, 0x05, 0xe4, 0x2c, 0xd0, 0x01, 0xe8, 0x20, - - 0x31, 0x95, 0xc6, 0x0a, 0x20, 0x82, 0x95, 0xf0, - 0x22, 0x90, 0x10, 0x20, 0x94, 0xbd, 0x20, 0x13, - - 0x98, 0xa5, 0x27, 0xd0, 0x19, 0x20, 0x1e, 0x8c, - 0x4c, 0x9b, 0x8b, 0x20, 0x94, 0xbd, 0x20, 0x13, - - 0x98, 0xa5, 0x27, 0xf0, 0x09, 0x20, 0xb4, 0xb4, - 0x4c, 0x9b, 0x8b, 0x4c, 0x2a, 0x98, 0x00, 0x06, - - 0x54, 0x79, 0x70, 0x65, 0x20, 0x6d, 0x69, 0x73, - 0x6d, 0x61, 0x74, 0x63, 0x68, 0x00, 0x20, 0xea, - - 0xbd, 0xa5, 0x2c, 0xc9, 0x80, 0xf0, 0x7b, 0xa0, - 0x02, 0xb1, 0x2a, 0xc5, 0x36, 0xb0, 0x55, 0xa5, - - 0x02, 0x85, 0x2c, 0xa5, 0x03, 0x85, 0x2d, 0xa5, - 0x36, 0xc9, 0x08, 0x90, 0x06, 0x69, 0x07, 0x90, - - 0x02, 0xa9, 0xff, 0x18, 0x48, 0xaa, 0xb1, 0x2a, - 0xa0, 0x00, 0x71, 0x2a, 0x45, 0x02, 0xd0, 0x0f, - - 0xc8, 0x71, 0x2a, 0x45, 0x03, 0xd0, 0x08, 0x85, - 0x2d, 0x8a, 0xc8, 0x38, 0xf1, 0x2a, 0xaa, 0x8a, - - 0x18, 0x65, 0x02, 0xa8, 0xa5, 0x03, 0x69, 0x00, - 0xc4, 0x04, 0xaa, 0xe5, 0x05, 0xb0, 0x48, 0x84, - - 0x02, 0x86, 0x03, 0x68, 0xa0, 0x02, 0x91, 0x2a, - 0x88, 0xa5, 0x2d, 0xf0, 0x07, 0x91, 0x2a, 0x88, - - 0xa5, 0x2c, 0x91, 0x2a, 0xa0, 0x03, 0xa5, 0x36, - 0x91, 0x2a, 0xf0, 0x15, 0x88, 0x88, 0xb1, 0x2a, - - 0x85, 0x2d, 0x88, 0xb1, 0x2a, 0x85, 0x2c, 0xb9, - 0x00, 0x06, 0x91, 0x2c, 0xc8, 0xc4, 0x36, 0xd0, - - 0xf6, 0x60, 0x20, 0xba, 0xbe, 0xc0, 0x00, 0xf0, - 0x0b, 0xb9, 0x00, 0x06, 0x91, 0x2a, 0x88, 0xd0, - - 0xf8, 0xad, 0x00, 0x06, 0x91, 0x2a, 0x60, 0x00, - 0x00, 0x4e, 0x6f, 0x20, 0x72, 0x6f, 0x6f, 0x6d, - - 0x00, 0xa5, 0x39, 0xc9, 0x80, 0xf0, 0x27, 0x90, - 0x3a, 0xa0, 0x00, 0xb1, 0x04, 0xaa, 0xf0, 0x15, - - 0xb1, 0x37, 0xe9, 0x01, 0x85, 0x39, 0xc8, 0xb1, - 0x37, 0xe9, 0x00, 0x85, 0x3a, 0xb1, 0x04, 0x91, - - 0x39, 0xc8, 0xca, 0xd0, 0xf8, 0xa1, 0x04, 0xa0, - 0x03, 0x91, 0x37, 0x4c, 0xdc, 0xbd, 0xa0, 0x00, - - 0xb1, 0x04, 0xaa, 0xf0, 0x0a, 0xc8, 0xb1, 0x04, - 0x88, 0x91, 0x37, 0xc8, 0xca, 0xd0, 0xf6, 0xa9, - - 0x0d, 0xd0, 0xe6, 0xa0, 0x00, 0xb1, 0x04, 0x91, - 0x37, 0xc8, 0xc4, 0x39, 0xb0, 0x18, 0xb1, 0x04, - - 0x91, 0x37, 0xc8, 0xb1, 0x04, 0x91, 0x37, 0xc8, - 0xb1, 0x04, 0x91, 0x37, 0xc8, 0xc4, 0x39, 0xb0, - - 0x05, 0xb1, 0x04, 0x91, 0x37, 0xc8, 0x98, 0x18, - 0x4c, 0xe1, 0xbd, 0xc6, 0x0a, 0x20, 0xa9, 0xbf, - - 0x98, 0x48, 0x20, 0x8c, 0x8a, 0xc9, 0x2c, 0xd0, - 0x3e, 0x20, 0x29, 0x9b, 0x20, 0x85, 0xa3, 0x68, - - 0xa8, 0xa5, 0x27, 0x20, 0xd4, 0xff, 0xaa, 0xf0, - 0x1b, 0x30, 0x0c, 0xa2, 0x03, 0xb5, 0x2a, 0x20, - - 0xd4, 0xff, 0xca, 0x10, 0xf8, 0x30, 0xd9, 0xa2, - 0x04, 0xbd, 0x6c, 0x04, 0x20, 0xd4, 0xff, 0xca, - - 0x10, 0xf7, 0x30, 0xcc, 0xa5, 0x36, 0x20, 0xd4, - 0xff, 0xaa, 0xf0, 0xc4, 0xbd, 0xff, 0x05, 0x20, - - 0xd4, 0xff, 0xca, 0xd0, 0xf7, 0xf0, 0xb9, 0x68, - 0x84, 0x0a, 0x4c, 0x98, 0x8b, 0x20, 0x25, 0xbc, - - 0x4c, 0x96, 0x8b, 0xa9, 0x00, 0x85, 0x14, 0x85, - 0x15, 0x20, 0x97, 0x8a, 0xc9, 0x3a, 0xf0, 0xf0, - - 0xc9, 0x0d, 0xf0, 0xec, 0xc9, 0x8b, 0xf0, 0xe8, - 0xd0, 0x38, 0x20, 0x97, 0x8a, 0xc9, 0x23, 0xf0, - - 0x8a, 0xc6, 0x0a, 0x4c, 0xbb, 0x8d, 0xad, 0x00, - 0x04, 0xf0, 0x10, 0xa5, 0x1e, 0xf0, 0x0c, 0xed, - - 0x00, 0x04, 0xb0, 0xf9, 0xa8, 0x20, 0x65, 0xb5, - 0xc8, 0xd0, 0xfa, 0x18, 0xad, 0x00, 0x04, 0x85, - - 0x14, 0x66, 0x15, 0x20, 0x97, 0x8a, 0xc9, 0x3a, - 0xf0, 0xb3, 0xc9, 0x0d, 0xf0, 0xaf, 0xc9, 0x8b, - - 0xf0, 0xab, 0xc9, 0x7e, 0xf0, 0xeb, 0xc9, 0x2c, - 0xf0, 0xcc, 0xc9, 0x3b, 0xf0, 0xa5, 0x20, 0x70, - - 0x8e, 0x90, 0xe0, 0xa5, 0x14, 0x48, 0xa5, 0x15, - 0x48, 0xc6, 0x1b, 0x20, 0x29, 0x9b, 0x68, 0x85, - - 0x15, 0x68, 0x85, 0x14, 0xa5, 0x1b, 0x85, 0x0a, - 0x98, 0xf0, 0x13, 0x20, 0xdf, 0x9e, 0xa5, 0x14, - - 0x38, 0xe5, 0x36, 0x90, 0x09, 0xf0, 0x07, 0xa8, - 0x20, 0x65, 0xb5, 0x88, 0xd0, 0xfa, 0xa5, 0x36, - - 0xf0, 0xb1, 0xa0, 0x00, 0xb9, 0x00, 0x06, 0x20, - 0x58, 0xb5, 0xc8, 0xc4, 0x36, 0xd0, 0xf5, 0xf0, - - 0xa2, 0x4c, 0xa2, 0x8a, 0xc9, 0x2c, 0xd0, 0xf9, - 0xa5, 0x2a, 0x48, 0x20, 0x56, 0xae, 0x20, 0xf0, - - 0x92, 0xa9, 0x1f, 0x20, 0xee, 0xff, 0x68, 0x20, - 0xee, 0xff, 0x20, 0x56, 0x94, 0x4c, 0x6a, 0x8e, - - 0x20, 0xdd, 0x92, 0x20, 0x8c, 0x8a, 0xc9, 0x29, - 0xd0, 0xda, 0xa5, 0x2a, 0xe5, 0x1e, 0xf0, 0x1a, - - 0xa8, 0xb0, 0x0c, 0x20, 0x25, 0xbc, 0xf0, 0x03, - 0x20, 0xe3, 0x92, 0xa4, 0x2a, 0xf0, 0x0b, 0x20, - - 0x65, 0xb5, 0x88, 0xd0, 0xfa, 0xf0, 0x03, 0x20, - 0x25, 0xbc, 0x18, 0xa4, 0x1b, 0x84, 0x0a, 0x60, - - 0xa6, 0x0b, 0x86, 0x19, 0xa6, 0x0c, 0x86, 0x1a, - 0xa6, 0x0a, 0x86, 0x1b, 0xc9, 0x27, 0xf0, 0xe7, - - 0xc9, 0x8a, 0xf0, 0xbc, 0xc9, 0x89, 0xf0, 0xd0, - 0x38, 0x60, 0x20, 0x97, 0x8a, 0x20, 0x70, 0x8e, - - 0x90, 0xf7, 0xc9, 0x22, 0xf0, 0x11, 0x38, 0x60, - 0x00, 0x09, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6e, - - 0x67, 0x20, 0x22, 0x00, 0x20, 0x58, 0xb5, 0xc8, - 0xb1, 0x19, 0xc9, 0x0d, 0xf0, 0xea, 0xc9, 0x22, - - 0xd0, 0xf2, 0xc8, 0x84, 0x1b, 0xb1, 0x19, 0xc9, - 0x22, 0xd0, 0xaf, 0xf0, 0xe7, 0x20, 0x57, 0x98, - - 0xa9, 0x10, 0xd0, 0x08, 0x20, 0x57, 0x98, 0x20, - 0x28, 0xbc, 0xa9, 0x0c, 0x20, 0xee, 0xff, 0x4c, - - 0x9b, 0x8b, 0x20, 0x1d, 0x9b, 0x20, 0xee, 0x92, - 0x20, 0x94, 0xbd, 0xa0, 0x00, 0x8c, 0x00, 0x06, - - 0x8c, 0xff, 0x06, 0x20, 0x8c, 0x8a, 0xc9, 0x2c, - 0xd0, 0x22, 0xa4, 0x1b, 0x20, 0xd5, 0x95, 0xf0, - - 0x2a, 0xac, 0xff, 0x06, 0xc8, 0xa5, 0x2a, 0x99, - 0x00, 0x06, 0xc8, 0xa5, 0x2b, 0x99, 0x00, 0x06, - - 0xc8, 0xa5, 0x2c, 0x99, 0x00, 0x06, 0xee, 0x00, - 0x06, 0x4c, 0xe0, 0x8e, 0xc6, 0x1b, 0x20, 0x52, - - 0x98, 0x20, 0xea, 0xbd, 0x20, 0x1e, 0x8f, 0xd8, - 0x4c, 0x9b, 0x8b, 0x4c, 0x43, 0xae, 0xad, 0x0c, - - 0x04, 0x4a, 0xad, 0x04, 0x04, 0xae, 0x60, 0x04, - 0xac, 0x64, 0x04, 0x6c, 0x2a, 0x00, 0x4c, 0x2a, - - 0x98, 0x20, 0xdf, 0x97, 0x90, 0xf8, 0x20, 0x94, - 0xbd, 0x20, 0x97, 0x8a, 0xc9, 0x2c, 0xd0, 0xee, - - 0x20, 0xdf, 0x97, 0x90, 0xe9, 0x20, 0x57, 0x98, - 0xa5, 0x2a, 0x85, 0x39, 0xa5, 0x2b, 0x85, 0x3a, - - 0x20, 0xea, 0xbd, 0x20, 0x2d, 0xbc, 0x20, 0x7b, - 0x98, 0x20, 0x22, 0x92, 0xa5, 0x39, 0xc5, 0x2a, - - 0xa5, 0x3a, 0xe5, 0x2b, 0xb0, 0xed, 0x4c, 0xf3, - 0x8a, 0xa9, 0x0a, 0x20, 0xd8, 0xae, 0x20, 0xdf, - - 0x97, 0x20, 0x94, 0xbd, 0xa9, 0x0a, 0x20, 0xd8, - 0xae, 0x20, 0x97, 0x8a, 0xc9, 0x2c, 0xd0, 0x0d, - - 0x20, 0xdf, 0x97, 0xa5, 0x2b, 0xd0, 0x58, 0xa5, - 0x2a, 0xf0, 0x54, 0xe6, 0x0a, 0xc6, 0x0a, 0x4c, - - 0x57, 0x98, 0xa5, 0x12, 0x85, 0x3b, 0xa5, 0x13, - 0x85, 0x3c, 0xa5, 0x18, 0x85, 0x38, 0xa9, 0x01, - - 0x85, 0x37, 0x60, 0x20, 0x69, 0x8f, 0xa2, 0x39, - 0x20, 0x0d, 0xbe, 0x20, 0x6f, 0xbe, 0x20, 0x92, - - 0x8f, 0xa0, 0x00, 0xb1, 0x37, 0x30, 0x30, 0x91, - 0x3b, 0xc8, 0xb1, 0x37, 0x91, 0x3b, 0x38, 0x98, - - 0x65, 0x3b, 0x85, 0x3b, 0xaa, 0xa5, 0x3c, 0x69, - 0x00, 0x85, 0x3c, 0xe4, 0x06, 0xe5, 0x07, 0xb0, - - 0x05, 0x20, 0x9f, 0x90, 0x90, 0xdb, 0x00, 0x00, - 0xcc, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x00, - - 0x00, 0x53, 0x69, 0x6c, 0x6c, 0x79, 0x00, 0x20, - 0x9a, 0x8f, 0xa0, 0x00, 0xb1, 0x37, 0x30, 0x1d, - - 0xa5, 0x3a, 0x91, 0x37, 0xa5, 0x39, 0xc8, 0x91, - 0x37, 0x18, 0xa5, 0x2a, 0x65, 0x39, 0x85, 0x39, - - 0xa9, 0x00, 0x65, 0x3a, 0x29, 0x7f, 0x85, 0x3a, - 0x20, 0x9f, 0x90, 0x90, 0xdd, 0xa5, 0x18, 0x85, - - 0x0c, 0xa0, 0x00, 0x84, 0x0b, 0xc8, 0xb1, 0x0b, - 0x30, 0x20, 0xa0, 0x04, 0xb1, 0x0b, 0xc9, 0x8d, - - 0xf0, 0x1b, 0xc8, 0xc9, 0x0d, 0xd0, 0xf5, 0xb1, - 0x0b, 0x30, 0x0f, 0xa0, 0x03, 0xb1, 0x0b, 0x18, - - 0x65, 0x0b, 0x85, 0x0b, 0x90, 0xe4, 0xe6, 0x0c, - 0xb0, 0xe0, 0x4c, 0xf3, 0x8a, 0x20, 0xeb, 0x97, - - 0x20, 0x92, 0x8f, 0xa0, 0x00, 0xb1, 0x37, 0x30, - 0x37, 0xb1, 0x3b, 0xc8, 0xc5, 0x2b, 0xd0, 0x21, - - 0xb1, 0x3b, 0xc5, 0x2a, 0xd0, 0x1b, 0xb1, 0x37, - 0x85, 0x3d, 0x88, 0xb1, 0x37, 0x85, 0x3e, 0xa4, - - 0x0a, 0x88, 0xa5, 0x0b, 0x85, 0x37, 0xa5, 0x0c, - 0x85, 0x38, 0x20, 0xf5, 0x88, 0xa4, 0x0a, 0xd0, - - 0xab, 0x20, 0x9f, 0x90, 0xa5, 0x3b, 0x69, 0x02, - 0x85, 0x3b, 0x90, 0xc7, 0xe6, 0x3c, 0xb0, 0xc3, - - 0x20, 0xcf, 0xbf, 0x46, 0x61, 0x69, 0x6c, 0x65, - 0x64, 0x20, 0x61, 0x74, 0x20, 0xc8, 0xb1, 0x0b, - - 0x85, 0x2b, 0xc8, 0xb1, 0x0b, 0x85, 0x2a, 0x20, - 0x1f, 0x99, 0x20, 0x25, 0xbc, 0xf0, 0xce, 0xc8, - - 0xb1, 0x37, 0x65, 0x37, 0x85, 0x37, 0x90, 0x03, - 0xe6, 0x38, 0x18, 0x60, 0x20, 0x69, 0x8f, 0xa5, - - 0x2a, 0x48, 0x20, 0xea, 0xbd, 0x20, 0x94, 0xbd, - 0x20, 0x23, 0x99, 0xa9, 0x20, 0x20, 0x02, 0xbc, - - 0x20, 0xea, 0xbd, 0x20, 0x51, 0x89, 0x20, 0x8d, - 0xbc, 0x20, 0x20, 0xbd, 0x68, 0x48, 0x18, 0x65, - - 0x2a, 0x85, 0x2a, 0x90, 0xe0, 0xe6, 0x2b, 0x10, - 0xdc, 0x4c, 0xf3, 0x8a, 0x4c, 0x18, 0x92, 0xc6, - - 0x0a, 0x20, 0x82, 0x95, 0xf0, 0x41, 0xb0, 0x3f, - 0x20, 0x94, 0xbd, 0x20, 0xdd, 0x92, 0x20, 0x22, - - 0x92, 0xa5, 0x2d, 0x05, 0x2c, 0xd0, 0x30, 0x18, - 0xa5, 0x2a, 0x65, 0x02, 0xa8, 0xa5, 0x2b, 0x65, - - 0x03, 0xaa, 0xc4, 0x04, 0xe5, 0x05, 0xb0, 0xd4, - 0xa5, 0x02, 0x85, 0x2a, 0xa5, 0x03, 0x85, 0x2b, - - 0x84, 0x02, 0x86, 0x03, 0xa9, 0x00, 0x85, 0x2c, - 0x85, 0x2d, 0xa9, 0x40, 0x85, 0x27, 0x20, 0xb4, - - 0xb4, 0x20, 0x27, 0x88, 0x4c, 0x0b, 0x92, 0x00, - 0x0a, 0x42, 0x61, 0x64, 0x20, 0xde, 0x00, 0x20, - - 0x97, 0x8a, 0x98, 0x18, 0x65, 0x0b, 0xa6, 0x0c, - 0x90, 0x02, 0xe8, 0x18, 0xe9, 0x00, 0x85, 0x37, - - 0x8a, 0xe9, 0x00, 0x85, 0x38, 0xa2, 0x05, 0x86, - 0x3f, 0xa6, 0x0a, 0x20, 0x59, 0x95, 0xc0, 0x01, - - 0xf0, 0xd5, 0xc9, 0x28, 0xf0, 0x15, 0xc9, 0x24, - 0xf0, 0x04, 0xc9, 0x25, 0xd0, 0x0a, 0xc6, 0x3f, - - 0xc8, 0xe8, 0xb1, 0x37, 0xc9, 0x28, 0xf0, 0x03, - 0x4c, 0xdf, 0x90, 0x84, 0x39, 0x86, 0x0a, 0x20, - - 0x69, 0x94, 0xd0, 0xb3, 0x20, 0xfc, 0x94, 0xa2, - 0x01, 0x20, 0x31, 0x95, 0xa5, 0x3f, 0x48, 0xa9, - - 0x01, 0x48, 0x20, 0xd8, 0xae, 0x20, 0x94, 0xbd, - 0x20, 0x21, 0x88, 0xa5, 0x2b, 0x29, 0xc0, 0x05, - - 0x2c, 0x05, 0x2d, 0xd0, 0x92, 0x20, 0x22, 0x92, - 0x68, 0xa8, 0xa5, 0x2a, 0x91, 0x02, 0xc8, 0xa5, - - 0x2b, 0x91, 0x02, 0xc8, 0x98, 0x48, 0x20, 0x31, - 0x92, 0x20, 0x97, 0x8a, 0xc9, 0x2c, 0xf0, 0xd5, - - 0xc9, 0x29, 0xf0, 0x03, 0x4c, 0x27, 0x91, 0x68, - 0x85, 0x15, 0x68, 0x85, 0x3f, 0xa9, 0x00, 0x85, - - 0x40, 0x20, 0x36, 0x92, 0xa0, 0x00, 0xa5, 0x15, - 0x91, 0x02, 0x65, 0x2a, 0x85, 0x2a, 0x90, 0x02, - - 0xe6, 0x2b, 0xa5, 0x03, 0x85, 0x38, 0xa5, 0x02, - 0x85, 0x37, 0x18, 0x65, 0x2a, 0xa8, 0xa5, 0x2b, - - 0x65, 0x03, 0xb0, 0x34, 0xaa, 0xc4, 0x04, 0xe5, - 0x05, 0xb0, 0x2d, 0x84, 0x02, 0x86, 0x03, 0xa5, - - 0x37, 0x65, 0x15, 0xa8, 0xa9, 0x00, 0x85, 0x37, - 0x90, 0x02, 0xe6, 0x38, 0x91, 0x37, 0xc8, 0xd0, - - 0x02, 0xe6, 0x38, 0xc4, 0x02, 0xd0, 0xf5, 0xe4, - 0x38, 0xd0, 0xf1, 0x20, 0x97, 0x8a, 0xc9, 0x2c, - - 0xf0, 0x03, 0x4c, 0x96, 0x8b, 0x4c, 0x2f, 0x91, - 0x00, 0x0b, 0xde, 0x20, 0x73, 0x70, 0x61, 0x63, - - 0x65, 0x00, 0xe6, 0x2a, 0xd0, 0x0a, 0xe6, 0x2b, - 0xd0, 0x06, 0xe6, 0x2c, 0xd0, 0x02, 0xe6, 0x2d, - - 0x60, 0xa2, 0x3f, 0x20, 0x0d, 0xbe, 0xa2, 0x00, - 0xa0, 0x00, 0x46, 0x40, 0x66, 0x3f, 0x90, 0x0b, - - 0x18, 0x98, 0x65, 0x2a, 0xa8, 0x8a, 0x65, 0x2b, - 0xaa, 0xb0, 0x0f, 0x06, 0x2a, 0x26, 0x2b, 0xa5, - - 0x3f, 0x05, 0x40, 0xd0, 0xe5, 0x84, 0x2a, 0x86, - 0x2b, 0x60, 0x4c, 0x27, 0x91, 0x20, 0xeb, 0x92, - - 0xa5, 0x2a, 0x85, 0x06, 0x85, 0x04, 0xa5, 0x2b, - 0x85, 0x07, 0x85, 0x05, 0x4c, 0x9b, 0x8b, 0x20, - - 0xeb, 0x92, 0xa5, 0x2a, 0x85, 0x00, 0x85, 0x02, - 0xa5, 0x2b, 0x85, 0x01, 0x85, 0x03, 0x20, 0x2f, - - 0xbd, 0xf0, 0x07, 0x20, 0xeb, 0x92, 0xa5, 0x2b, - 0x85, 0x18, 0x4c, 0x9b, 0x8b, 0x20, 0x57, 0x98, - - 0x20, 0x20, 0xbd, 0xf0, 0xf5, 0x20, 0xdf, 0x97, - 0xb0, 0x0b, 0xc9, 0xee, 0xf0, 0x19, 0xc9, 0x87, - - 0xf0, 0x1e, 0x20, 0x21, 0x88, 0x20, 0x57, 0x98, - 0xa5, 0x2a, 0x85, 0x21, 0xa5, 0x2b, 0x85, 0x22, - - 0xa9, 0xff, 0x85, 0x20, 0x4c, 0x9b, 0x8b, 0xe6, - 0x0a, 0x20, 0x57, 0x98, 0xa9, 0xff, 0xd0, 0xee, - - 0xe6, 0x0a, 0x20, 0x57, 0x98, 0xa9, 0x00, 0xf0, - 0xe9, 0x20, 0xeb, 0x92, 0xa2, 0x2a, 0xa0, 0x00, - - 0x84, 0x2e, 0xa9, 0x02, 0x20, 0xf1, 0xff, 0x4c, - 0x9b, 0x8b, 0x20, 0xae, 0x8a, 0x20, 0x29, 0x9b, - - 0x4c, 0xf0, 0x92, 0x20, 0xec, 0xad, 0xf0, 0x0f, - 0x30, 0x0a, 0x60, 0x20, 0x07, 0x98, 0xa5, 0x27, - - 0xf0, 0x05, 0x10, 0xf6, 0x4c, 0xe4, 0xa3, 0x4c, - 0x0e, 0x8c, 0x20, 0xec, 0xad, 0xf0, 0xf8, 0x30, - - 0xe9, 0x4c, 0xbe, 0xa2, 0xa5, 0x0b, 0x85, 0x19, - 0xa5, 0x0c, 0x85, 0x1a, 0xa5, 0x0a, 0x85, 0x1b, - - 0xa9, 0xf2, 0x20, 0x97, 0xb1, 0x20, 0x52, 0x98, - 0x4c, 0x9b, 0x8b, 0xa0, 0x03, 0xa9, 0x00, 0x91, - - 0x2a, 0xf0, 0x1e, 0xba, 0xe0, 0xfc, 0xb0, 0x43, - 0x20, 0x82, 0x95, 0xf0, 0x26, 0x20, 0x0d, 0xb3, - - 0xa4, 0x2c, 0x30, 0xe7, 0x20, 0x94, 0xbd, 0xa9, - 0x00, 0x20, 0xd8, 0xae, 0x85, 0x27, 0x20, 0xb4, - - 0xb4, 0xba, 0xfe, 0x06, 0x01, 0xa4, 0x1b, 0x84, - 0x0a, 0x20, 0x97, 0x8a, 0xc9, 0x2c, 0xf0, 0xd3, - - 0x4c, 0x96, 0x8b, 0x4c, 0x98, 0x8b, 0xba, 0xe0, - 0xfc, 0xb0, 0x0a, 0xad, 0xff, 0x01, 0xc9, 0xf2, - - 0xd0, 0x03, 0x4c, 0x57, 0x98, 0x00, 0x0d, 0x4e, - 0x6f, 0x20, 0xf2, 0x00, 0x0c, 0x4e, 0x6f, 0x74, - - 0x20, 0xea, 0x00, 0x19, 0x42, 0x61, 0x64, 0x20, - 0xeb, 0x00, 0x20, 0x21, 0x88, 0xa5, 0x2a, 0x48, - - 0x20, 0xda, 0x92, 0x20, 0x52, 0x98, 0xa9, 0x12, - 0x20, 0xee, 0xff, 0x4c, 0xda, 0x93, 0xa9, 0x11, - - 0x48, 0x20, 0x21, 0x88, 0x20, 0x57, 0x98, 0x4c, - 0xda, 0x93, 0xa9, 0x16, 0x48, 0x20, 0x21, 0x88, - - 0x20, 0x57, 0x98, 0x20, 0xe7, 0xbe, 0xe0, 0xff, - 0xd0, 0x2d, 0xc0, 0xff, 0xd0, 0x29, 0xa5, 0x04, - - 0xc5, 0x06, 0xd0, 0xbe, 0xa5, 0x05, 0xc5, 0x07, - 0xd0, 0xb8, 0xa6, 0x2a, 0xa9, 0x85, 0x20, 0xf4, - - 0xff, 0xe4, 0x02, 0x98, 0xe5, 0x03, 0x90, 0xaa, - 0xe4, 0x12, 0x98, 0xe5, 0x13, 0x90, 0xa3, 0x86, - - 0x06, 0x86, 0x04, 0x84, 0x07, 0x84, 0x05, 0x20, - 0x28, 0xbc, 0x68, 0x20, 0xee, 0xff, 0x20, 0x56, - - 0x94, 0x4c, 0x9b, 0x8b, 0xa9, 0x04, 0xd0, 0x02, - 0xa9, 0x05, 0x48, 0x20, 0x1d, 0x9b, 0x4c, 0xfd, - - 0x93, 0x20, 0x21, 0x88, 0xa5, 0x2a, 0x48, 0x20, - 0xae, 0x8a, 0x20, 0x29, 0x9b, 0x20, 0xee, 0x92, - - 0x20, 0x94, 0xbd, 0x20, 0xda, 0x92, 0x20, 0x52, - 0x98, 0xa9, 0x19, 0x20, 0xee, 0xff, 0x68, 0x20, - - 0xee, 0xff, 0x20, 0x0b, 0xbe, 0xa5, 0x37, 0x20, - 0xee, 0xff, 0xa5, 0x38, 0x20, 0xee, 0xff, 0x20, - - 0x56, 0x94, 0xa5, 0x2b, 0x20, 0xee, 0xff, 0x4c, - 0x9b, 0x8b, 0xa5, 0x2b, 0x20, 0xee, 0xff, 0x20, - - 0x97, 0x8a, 0xc9, 0x3a, 0xf0, 0x1d, 0xc9, 0x0d, - 0xf0, 0x19, 0xc9, 0x8b, 0xf0, 0x15, 0xc6, 0x0a, - - 0x20, 0x21, 0x88, 0x20, 0x56, 0x94, 0x20, 0x97, - 0x8a, 0xc9, 0x2c, 0xf0, 0xe2, 0xc9, 0x3b, 0xd0, - - 0xe1, 0xf0, 0xd7, 0x4c, 0x96, 0x8b, 0xa5, 0x2a, - 0x6c, 0x0e, 0x02, 0xa0, 0x01, 0xb1, 0x37, 0xa0, - - 0xf6, 0xc9, 0xf2, 0xf0, 0x0a, 0xa0, 0xf8, 0xd0, - 0x06, 0xa0, 0x01, 0xb1, 0x37, 0x0a, 0xa8, 0xb9, - - 0x00, 0x04, 0x85, 0x3a, 0xb9, 0x01, 0x04, 0x85, - 0x3b, 0xa5, 0x3b, 0xf0, 0x35, 0xa0, 0x00, 0xb1, - - 0x3a, 0x85, 0x3c, 0xc8, 0xb1, 0x3a, 0x85, 0x3d, - 0xc8, 0xb1, 0x3a, 0xd0, 0x0d, 0x88, 0xc4, 0x39, - - 0xd0, 0x21, 0xc8, 0xb0, 0x12, 0xc8, 0xb1, 0x3a, - 0xf0, 0x19, 0xd1, 0x37, 0xd0, 0x15, 0xc4, 0x39, - - 0xd0, 0xf3, 0xc8, 0xb1, 0x3a, 0xd0, 0x0c, 0x98, - 0x65, 0x3a, 0x85, 0x2a, 0xa5, 0x3b, 0x69, 0x00, - - 0x85, 0x2b, 0x60, 0xa5, 0x3d, 0xf0, 0xfb, 0xa0, - 0x00, 0xb1, 0x3c, 0x85, 0x3a, 0xc8, 0xb1, 0x3c, - - 0x85, 0x3b, 0xc8, 0xb1, 0x3c, 0xd0, 0x0d, 0x88, - 0xc4, 0x39, 0xd0, 0xad, 0xc8, 0xb0, 0x12, 0xc8, - - 0xb1, 0x3c, 0xf0, 0xa5, 0xd1, 0x37, 0xd0, 0xa1, - 0xc4, 0x39, 0xd0, 0xf3, 0xc8, 0xb1, 0x3c, 0xd0, - - 0x98, 0x98, 0x65, 0x3c, 0x85, 0x2a, 0xa5, 0x3d, - 0x69, 0x00, 0x85, 0x2b, 0x60, 0xa0, 0x01, 0xb1, - - 0x37, 0xaa, 0xa9, 0xf6, 0xe0, 0xf2, 0xf0, 0x09, - 0xa9, 0xf8, 0xd0, 0x05, 0xa0, 0x01, 0xb1, 0x37, - - 0x0a, 0x85, 0x3a, 0xa9, 0x04, 0x85, 0x3b, 0xb1, - 0x3a, 0xf0, 0x0b, 0xaa, 0x88, 0xb1, 0x3a, 0x85, - - 0x3a, 0x86, 0x3b, 0xc8, 0x10, 0xf1, 0xa5, 0x03, - 0x91, 0x3a, 0xa5, 0x02, 0x88, 0x91, 0x3a, 0x98, - - 0xc8, 0x91, 0x02, 0xc4, 0x39, 0xf0, 0x31, 0xc8, - 0xb1, 0x37, 0x91, 0x02, 0xc4, 0x39, 0xd0, 0xf7, - - 0x60, 0xa9, 0x00, 0xc8, 0x91, 0x02, 0xca, 0xd0, - 0xfa, 0x38, 0x98, 0x65, 0x02, 0x90, 0x02, 0xe6, - - 0x03, 0xa4, 0x03, 0xc4, 0x05, 0x90, 0x0f, 0xd0, - 0x04, 0xc5, 0x04, 0x90, 0x09, 0xa9, 0x00, 0xa0, - - 0x01, 0x91, 0x3a, 0x4c, 0xb7, 0x8c, 0x85, 0x02, - 0x60, 0xa0, 0x01, 0xb1, 0x37, 0xc9, 0x30, 0x90, - - 0x18, 0xc9, 0x40, 0xb0, 0x0c, 0xc9, 0x3a, 0xb0, - 0x10, 0xc0, 0x01, 0xf0, 0x0c, 0xe8, 0xc8, 0xd0, - - 0xea, 0xc9, 0x5f, 0xb0, 0x05, 0xc9, 0x5b, 0x90, - 0xf4, 0x60, 0xc9, 0x7b, 0x90, 0xef, 0x60, 0x20, - - 0x31, 0x95, 0x20, 0xc9, 0x95, 0xd0, 0x1d, 0xb0, - 0x1b, 0x20, 0xfc, 0x94, 0xa2, 0x05, 0xe4, 0x2c, - - 0xd0, 0xed, 0xe8, 0xd0, 0xea, 0xc9, 0x21, 0xf0, - 0x0c, 0xc9, 0x24, 0xf0, 0x13, 0x49, 0x3f, 0xf0, - - 0x06, 0xa9, 0x00, 0x38, 0x60, 0xa9, 0x04, 0x48, - 0xe6, 0x1b, 0x20, 0xe3, 0x92, 0x4c, 0x9f, 0x96, - - 0xe6, 0x1b, 0x20, 0xe3, 0x92, 0xa5, 0x2b, 0xf0, - 0x06, 0xa9, 0x80, 0x85, 0x2c, 0x38, 0x60, 0x00, - - 0x08, 0x24, 0x20, 0x72, 0x61, 0x6e, 0x67, 0x65, - 0x00, 0xa5, 0x0b, 0x85, 0x19, 0xa5, 0x0c, 0x85, - - 0x1a, 0xa4, 0x0a, 0x88, 0xc8, 0x84, 0x1b, 0xb1, - 0x19, 0xc9, 0x20, 0xf0, 0xf7, 0xc9, 0x40, 0x90, - - 0xb4, 0xc9, 0x5b, 0xb0, 0x1a, 0x0a, 0x0a, 0x85, - 0x2a, 0xa9, 0x04, 0x85, 0x2b, 0xc8, 0xb1, 0x19, - - 0xc8, 0xc9, 0x25, 0xd0, 0x0a, 0xa2, 0x04, 0x86, - 0x2c, 0xb1, 0x19, 0xc9, 0x28, 0xd0, 0x66, 0xa2, - - 0x05, 0x86, 0x2c, 0xa5, 0x1b, 0x18, 0x65, 0x19, - 0xa6, 0x1a, 0x90, 0x02, 0xe8, 0x18, 0xe9, 0x00, - - 0x85, 0x37, 0xb0, 0x01, 0xca, 0x86, 0x38, 0xa6, - 0x1b, 0xa0, 0x01, 0xb1, 0x37, 0xc9, 0x41, 0xb0, - - 0x0c, 0xc9, 0x30, 0x90, 0x1c, 0xc9, 0x3a, 0xb0, - 0x18, 0xe8, 0xc8, 0xd0, 0xee, 0xc9, 0x5b, 0xb0, - - 0x04, 0xe8, 0xc8, 0xd0, 0xe6, 0xc9, 0x5f, 0x90, - 0x08, 0xc9, 0x7b, 0xb0, 0x04, 0xe8, 0xc8, 0xd0, - - 0xda, 0x88, 0xf0, 0x2f, 0xc9, 0x24, 0xf0, 0x67, - 0xc9, 0x25, 0xd0, 0x08, 0xc6, 0x2c, 0xc8, 0xe8, - - 0xc8, 0xb1, 0x37, 0x88, 0x84, 0x39, 0xc9, 0x28, - 0xf0, 0x4c, 0x20, 0x69, 0x94, 0xf0, 0x18, 0x86, - - 0x1b, 0xa4, 0x1b, 0xb1, 0x19, 0xc9, 0x21, 0xf0, - 0x16, 0xc9, 0x3f, 0xf0, 0x0e, 0x18, 0x84, 0x1b, - - 0xa9, 0xff, 0x60, 0xa9, 0x00, 0x38, 0x60, 0xa9, - 0x00, 0x18, 0x60, 0xa9, 0x00, 0xf0, 0x02, 0xa9, - - 0x04, 0x48, 0xc8, 0x84, 0x1b, 0x20, 0x2c, 0xb3, - 0x20, 0xf0, 0x92, 0xa5, 0x2b, 0x48, 0xa5, 0x2a, - - 0x48, 0x20, 0xe3, 0x92, 0x18, 0x68, 0x65, 0x2a, - 0x85, 0x2a, 0x68, 0x65, 0x2b, 0x85, 0x2b, 0x68, - - 0x85, 0x2c, 0x18, 0xa9, 0xff, 0x60, 0xe8, 0xe6, - 0x39, 0x20, 0xdf, 0x96, 0x4c, 0x61, 0x96, 0xe8, - - 0xc8, 0x84, 0x39, 0xc8, 0xc6, 0x2c, 0xb1, 0x37, - 0xc9, 0x28, 0xf0, 0x0d, 0x20, 0x69, 0x94, 0xf0, - - 0xb6, 0x86, 0x1b, 0xa9, 0x81, 0x85, 0x2c, 0x38, - 0x60, 0xe8, 0x84, 0x39, 0xc6, 0x2c, 0x20, 0xdf, - - 0x96, 0xa9, 0x81, 0x85, 0x2c, 0x38, 0x60, 0x00, - 0x0e, 0x41, 0x72, 0x72, 0x61, 0x79, 0x00, 0x20, - - 0x69, 0x94, 0xf0, 0xf3, 0x86, 0x1b, 0xa5, 0x2c, - 0x48, 0xa5, 0x2a, 0x48, 0xa5, 0x2b, 0x48, 0xa0, - - 0x00, 0xb1, 0x2a, 0xc9, 0x04, 0x90, 0x75, 0x98, - 0x20, 0xd8, 0xae, 0xa9, 0x01, 0x85, 0x2d, 0x20, - - 0x94, 0xbd, 0x20, 0xdd, 0x92, 0xe6, 0x1b, 0xe0, - 0x2c, 0xd0, 0xcc, 0xa2, 0x39, 0x20, 0x0d, 0xbe, - - 0xa4, 0x3c, 0x68, 0x85, 0x38, 0x68, 0x85, 0x37, - 0x48, 0xa5, 0x38, 0x48, 0x20, 0xba, 0x97, 0x84, - - 0x2d, 0xb1, 0x37, 0x85, 0x3f, 0xc8, 0xb1, 0x37, - 0x85, 0x40, 0xa5, 0x2a, 0x65, 0x39, 0x85, 0x2a, - - 0xa5, 0x2b, 0x65, 0x3a, 0x85, 0x2b, 0x20, 0x36, - 0x92, 0xa0, 0x00, 0x38, 0xb1, 0x37, 0xe5, 0x2d, - - 0xc9, 0x03, 0xb0, 0xbb, 0x20, 0x94, 0xbd, 0x20, - 0x56, 0xae, 0x20, 0xf0, 0x92, 0x68, 0x85, 0x38, - - 0x68, 0x85, 0x37, 0xa2, 0x39, 0x20, 0x0d, 0xbe, - 0xa4, 0x3c, 0x20, 0xba, 0x97, 0x18, 0xa5, 0x39, - - 0x65, 0x2a, 0x85, 0x2a, 0xa5, 0x3a, 0x65, 0x2b, - 0x85, 0x2b, 0x90, 0x11, 0x20, 0x56, 0xae, 0x20, - - 0xf0, 0x92, 0x68, 0x85, 0x38, 0x68, 0x85, 0x37, - 0xa0, 0x01, 0x20, 0xba, 0x97, 0x68, 0x85, 0x2c, - - 0xc9, 0x05, 0xd0, 0x17, 0xa6, 0x2b, 0xa5, 0x2a, - 0x06, 0x2a, 0x26, 0x2b, 0x06, 0x2a, 0x26, 0x2b, - - 0x65, 0x2a, 0x85, 0x2a, 0x8a, 0x65, 0x2b, 0x85, - 0x2b, 0x90, 0x08, 0x06, 0x2a, 0x26, 0x2b, 0x06, - - 0x2a, 0x26, 0x2b, 0x98, 0x65, 0x2a, 0x85, 0x2a, - 0x90, 0x03, 0xe6, 0x2b, 0x18, 0xa5, 0x37, 0x65, - - 0x2a, 0x85, 0x2a, 0xa5, 0x38, 0x65, 0x2b, 0x85, - 0x2b, 0x60, 0xa5, 0x2b, 0x29, 0xc0, 0x05, 0x2c, - - 0x05, 0x2d, 0xd0, 0x0d, 0xa5, 0x2a, 0xd1, 0x37, - 0xc8, 0xa5, 0x2b, 0xf1, 0x37, 0xb0, 0x02, 0xc8, - - 0x60, 0x00, 0x0f, 0x53, 0x75, 0x62, 0x73, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x00, 0xe6, 0x0a, 0xa4, - - 0x0a, 0xb1, 0x0b, 0xc9, 0x20, 0xf0, 0xf6, 0xc9, - 0x8d, 0xd0, 0x1a, 0xc8, 0xb1, 0x0b, 0x0a, 0x0a, - - 0xaa, 0x29, 0xc0, 0xc8, 0x51, 0x0b, 0x85, 0x2a, - 0x8a, 0x0a, 0x0a, 0xc8, 0x51, 0x0b, 0x85, 0x2b, - - 0xc8, 0x84, 0x0a, 0x38, 0x60, 0x18, 0x60, 0xa5, - 0x0b, 0x85, 0x19, 0xa5, 0x0c, 0x85, 0x1a, 0xa5, - - 0x0a, 0x85, 0x1b, 0xa4, 0x1b, 0xe6, 0x1b, 0xb1, - 0x19, 0xc9, 0x20, 0xf0, 0xf6, 0xc9, 0x3d, 0xf0, - - 0x28, 0x00, 0x04, 0x4d, 0x69, 0x73, 0x74, 0x61, - 0x6b, 0x65, 0x00, 0x10, 0x53, 0x79, 0x6e, 0x74, - - 0x61, 0x78, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, - 0x00, 0x11, 0x45, 0x73, 0x63, 0x61, 0x70, 0x65, - - 0x00, 0x20, 0x8c, 0x8a, 0xc9, 0x3d, 0xd0, 0xd9, - 0x60, 0x20, 0x29, 0x9b, 0x8a, 0xa4, 0x1b, 0x4c, - - 0x61, 0x98, 0xa4, 0x1b, 0x4c, 0x59, 0x98, 0xa4, - 0x0a, 0x88, 0xc8, 0xb1, 0x0b, 0xc9, 0x20, 0xf0, - - 0xf9, 0xc9, 0x3a, 0xf0, 0x08, 0xc9, 0x0d, 0xf0, - 0x04, 0xc9, 0x8b, 0xd0, 0xbd, 0x18, 0x98, 0x65, - - 0x0b, 0x85, 0x0b, 0x90, 0x02, 0xe6, 0x0c, 0xa0, - 0x01, 0x84, 0x0a, 0x24, 0xff, 0x30, 0xb9, 0x60, - - 0x20, 0x57, 0x98, 0x88, 0xb1, 0x0b, 0xc9, 0x3a, - 0xf0, 0xf5, 0xa5, 0x0c, 0xc9, 0x07, 0xf0, 0x2c, - - 0xc8, 0xb1, 0x0b, 0x30, 0x27, 0xa5, 0x20, 0xf0, - 0x13, 0x98, 0x48, 0xc8, 0xb1, 0x0b, 0x48, 0x88, - - 0xb1, 0x0b, 0xa8, 0x68, 0x20, 0xea, 0xae, 0x20, - 0x05, 0x99, 0x68, 0xa8, 0xc8, 0x38, 0x98, 0x65, - - 0x0b, 0x85, 0x0b, 0x90, 0x02, 0xe6, 0x0c, 0xa0, - 0x01, 0x84, 0x0a, 0x60, 0x4c, 0xf6, 0x8a, 0x4c, - - 0x0e, 0x8c, 0x20, 0x1d, 0x9b, 0xf0, 0xf8, 0x10, - 0x03, 0x20, 0xe4, 0xa3, 0xa4, 0x1b, 0x84, 0x0a, - - 0xa5, 0x2a, 0x05, 0x2b, 0x05, 0x2c, 0x05, 0x2d, - 0xf0, 0x17, 0xe0, 0x8c, 0xf0, 0x03, 0x4c, 0xa3, - - 0x8b, 0xe6, 0x0a, 0x20, 0xdf, 0x97, 0x90, 0xf6, - 0x20, 0xaf, 0xb9, 0x20, 0x77, 0x98, 0x4c, 0xd2, - - 0xb8, 0xa4, 0x0a, 0xb1, 0x0b, 0xc9, 0x0d, 0xf0, - 0x09, 0xc8, 0xc9, 0x8b, 0xd0, 0xf5, 0x84, 0x0a, - - 0xf0, 0xe1, 0x4c, 0x87, 0x8b, 0xa5, 0x2a, 0xc5, - 0x21, 0xa5, 0x2b, 0xe5, 0x22, 0xb0, 0xac, 0xa9, - - 0x5b, 0x20, 0x58, 0xb5, 0x20, 0x1f, 0x99, 0xa9, - 0x5d, 0x20, 0x58, 0xb5, 0x4c, 0x65, 0xb5, 0xa9, - - 0x00, 0xf0, 0x02, 0xa9, 0x05, 0x85, 0x14, 0xa2, - 0x04, 0xa9, 0x00, 0x95, 0x3f, 0x38, 0xa5, 0x2a, - - 0xfd, 0x6b, 0x99, 0xa8, 0xa5, 0x2b, 0xfd, 0xb9, - 0x99, 0x90, 0x08, 0x85, 0x2b, 0x84, 0x2a, 0xf6, - - 0x3f, 0xd0, 0xeb, 0xca, 0x10, 0xe3, 0xa2, 0x05, - 0xca, 0xf0, 0x04, 0xb5, 0x3f, 0xf0, 0xf9, 0x86, - - 0x37, 0xa5, 0x14, 0xf0, 0x0b, 0xe5, 0x37, 0xf0, - 0x07, 0xa8, 0x20, 0x65, 0xb5, 0x88, 0xd0, 0xfa, - - 0xb5, 0x3f, 0x09, 0x30, 0x20, 0x58, 0xb5, 0xca, - 0x10, 0xf6, 0x60, 0x01, 0x0a, 0x64, 0xe8, 0x10, - - 0xa0, 0x00, 0x84, 0x3d, 0xa5, 0x18, 0x85, 0x3e, - 0xa0, 0x01, 0xb1, 0x3d, 0xc5, 0x2b, 0xb0, 0x0e, - - 0xa0, 0x03, 0xb1, 0x3d, 0x65, 0x3d, 0x85, 0x3d, - 0x90, 0xee, 0xe6, 0x3e, 0xb0, 0xea, 0xd0, 0x14, - - 0xa0, 0x02, 0xb1, 0x3d, 0xc5, 0x2a, 0x90, 0xe8, - 0xd0, 0x0a, 0x98, 0x65, 0x3d, 0x85, 0x3d, 0x90, - - 0x03, 0xe6, 0x3e, 0x18, 0xa0, 0x02, 0x60, 0x00, - 0x12, 0x44, 0x69, 0x76, 0x69, 0x73, 0x69, 0x6f, - - 0x6e, 0x20, 0x62, 0x79, 0x20, 0x7a, 0x65, 0x72, - 0x6f, 0x00, 0x00, 0x00, 0x03, 0x27, 0xa8, 0x20, - - 0xf0, 0x92, 0xa5, 0x2d, 0x48, 0x20, 0x71, 0xad, - 0x20, 0x1d, 0x9e, 0x86, 0x27, 0xa8, 0x20, 0xf0, - - 0x92, 0x68, 0x85, 0x38, 0x45, 0x2d, 0x85, 0x37, - 0x20, 0x71, 0xad, 0xa2, 0x39, 0x20, 0x0d, 0xbe, - - 0x84, 0x3d, 0x84, 0x3e, 0x84, 0x3f, 0x84, 0x40, - 0xa5, 0x2d, 0x05, 0x2a, 0x05, 0x2b, 0x05, 0x2c, - - 0xf0, 0xb5, 0xa0, 0x20, 0x88, 0xf0, 0x41, 0x06, - 0x39, 0x26, 0x3a, 0x26, 0x3b, 0x26, 0x3c, 0x10, - - 0xf3, 0x26, 0x39, 0x26, 0x3a, 0x26, 0x3b, 0x26, - 0x3c, 0x26, 0x3d, 0x26, 0x3e, 0x26, 0x3f, 0x26, - - 0x40, 0x38, 0xa5, 0x3d, 0xe5, 0x2a, 0x48, 0xa5, - 0x3e, 0xe5, 0x2b, 0x48, 0xa5, 0x3f, 0xe5, 0x2c, - - 0xaa, 0xa5, 0x40, 0xe5, 0x2d, 0x90, 0x0c, 0x85, - 0x40, 0x86, 0x3f, 0x68, 0x85, 0x3e, 0x68, 0x85, - - 0x3d, 0xb0, 0x02, 0x68, 0x68, 0x88, 0xd0, 0xc9, - 0x60, 0x86, 0x27, 0x20, 0xea, 0xbd, 0x20, 0x51, - - 0xbd, 0x20, 0xbe, 0xa2, 0x20, 0x1e, 0xa2, 0x20, - 0x7e, 0xbd, 0x20, 0xb5, 0xa3, 0x4c, 0x62, 0x9a, - - 0x20, 0x51, 0xbd, 0x20, 0x42, 0x9c, 0x86, 0x27, - 0xa8, 0x20, 0xfd, 0x92, 0x20, 0x7e, 0xbd, 0x20, - - 0x4e, 0xa3, 0xa6, 0x27, 0xa0, 0x00, 0xa5, 0x3b, - 0x29, 0x80, 0x85, 0x3b, 0xa5, 0x2e, 0x29, 0x80, - - 0xc5, 0x3b, 0xd0, 0x1e, 0xa5, 0x3d, 0xc5, 0x30, - 0xd0, 0x19, 0xa5, 0x3e, 0xc5, 0x31, 0xd0, 0x13, - - 0xa5, 0x3f, 0xc5, 0x32, 0xd0, 0x0d, 0xa5, 0x40, - 0xc5, 0x33, 0xd0, 0x07, 0xa5, 0x41, 0xc5, 0x34, - - 0xd0, 0x01, 0x60, 0x6a, 0x45, 0x3b, 0x2a, 0xa9, - 0x01, 0x60, 0x4c, 0x0e, 0x8c, 0x8a, 0xf0, 0x47, - - 0x30, 0xae, 0x20, 0x94, 0xbd, 0x20, 0x42, 0x9c, - 0xa8, 0xf0, 0xef, 0x30, 0x8c, 0xa5, 0x2d, 0x49, - - 0x80, 0x85, 0x2d, 0x38, 0xa0, 0x00, 0xb1, 0x04, - 0xe5, 0x2a, 0x85, 0x2a, 0xc8, 0xb1, 0x04, 0xe5, - - 0x2b, 0x85, 0x2b, 0xc8, 0xb1, 0x04, 0xe5, 0x2c, - 0x85, 0x2c, 0xc8, 0xb1, 0x04, 0xa0, 0x00, 0x49, - - 0x80, 0xe5, 0x2d, 0x05, 0x2a, 0x05, 0x2b, 0x05, - 0x2c, 0x08, 0x18, 0xa9, 0x04, 0x65, 0x04, 0x85, - - 0x04, 0x90, 0x02, 0xe6, 0x05, 0x28, 0x60, 0x20, - 0xb2, 0xbd, 0x20, 0x42, 0x9c, 0xa8, 0xd0, 0xaa, - - 0x86, 0x37, 0xa6, 0x36, 0xa0, 0x00, 0xb1, 0x04, - 0x85, 0x39, 0xc5, 0x36, 0xb0, 0x01, 0xaa, 0x86, - - 0x3a, 0xa0, 0x00, 0xc4, 0x3a, 0xf0, 0x0a, 0xc8, - 0xb1, 0x04, 0xd9, 0xff, 0x05, 0xf0, 0xf4, 0xd0, - - 0x04, 0xa5, 0x39, 0xc5, 0x36, 0x08, 0x20, 0xdc, - 0xbd, 0xa6, 0x37, 0x28, 0x60, 0xa5, 0x0b, 0x85, - - 0x19, 0xa5, 0x0c, 0x85, 0x1a, 0xa5, 0x0a, 0x85, - 0x1b, 0x20, 0x72, 0x9b, 0xe0, 0x84, 0xf0, 0x0a, - - 0xe0, 0x82, 0xf0, 0x21, 0xc6, 0x1b, 0xa8, 0x85, - 0x27, 0x60, 0x20, 0x6b, 0x9b, 0xa8, 0x20, 0xf0, - - 0x92, 0xa0, 0x03, 0xb1, 0x04, 0x19, 0x2a, 0x00, - 0x99, 0x2a, 0x00, 0x88, 0x10, 0xf5, 0x20, 0xff, - - 0xbd, 0xa9, 0x40, 0xd0, 0xd7, 0x20, 0x6b, 0x9b, - 0xa8, 0x20, 0xf0, 0x92, 0xa0, 0x03, 0xb1, 0x04, - - 0x59, 0x2a, 0x00, 0x99, 0x2a, 0x00, 0x88, 0x10, - 0xf5, 0x30, 0xe3, 0xa8, 0x20, 0xf0, 0x92, 0x20, - - 0x94, 0xbd, 0x20, 0x9c, 0x9b, 0xe0, 0x80, 0xf0, - 0x01, 0x60, 0xa8, 0x20, 0xf0, 0x92, 0x20, 0x94, - - 0xbd, 0x20, 0x9c, 0x9b, 0xa8, 0x20, 0xf0, 0x92, - 0xa0, 0x03, 0xb1, 0x04, 0x39, 0x2a, 0x00, 0x99, - - 0x2a, 0x00, 0x88, 0x10, 0xf5, 0x20, 0xff, 0xbd, - 0xa9, 0x40, 0xd0, 0xd9, 0x20, 0x42, 0x9c, 0xe0, - - 0x3f, 0xb0, 0x04, 0xe0, 0x3c, 0xb0, 0x01, 0x60, - 0xf0, 0x16, 0xe0, 0x3e, 0xf0, 0x3a, 0xaa, 0x20, - - 0x9e, 0x9a, 0xd0, 0x01, 0x88, 0x84, 0x2a, 0x84, - 0x2b, 0x84, 0x2c, 0x84, 0x2d, 0xa9, 0x40, 0x60, - - 0xaa, 0xa4, 0x1b, 0xb1, 0x19, 0xc9, 0x3d, 0xf0, - 0x0b, 0xc9, 0x3e, 0xf0, 0x12, 0x20, 0x9d, 0x9a, - - 0x90, 0xe2, 0xb0, 0xe1, 0xe6, 0x1b, 0x20, 0x9d, - 0x9a, 0xf0, 0xd9, 0x90, 0xd7, 0xb0, 0xd6, 0xe6, - - 0x1b, 0x20, 0x9d, 0x9a, 0xd0, 0xce, 0xf0, 0xcd, - 0xaa, 0xa4, 0x1b, 0xb1, 0x19, 0xc9, 0x3d, 0xf0, - - 0x09, 0x20, 0x9d, 0x9a, 0xf0, 0xbf, 0xb0, 0xbc, - 0x90, 0xbb, 0xe6, 0x1b, 0x20, 0x9d, 0x9a, 0xb0, - - 0xb3, 0x90, 0xb2, 0x00, 0x13, 0x53, 0x74, 0x72, - 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x6f, 0x20, - - 0x6c, 0x6f, 0x6e, 0x67, 0x00, 0x20, 0xb2, 0xbd, - 0x20, 0x20, 0x9e, 0xa8, 0xd0, 0x6a, 0x18, 0x86, - - 0x37, 0xa0, 0x00, 0xb1, 0x04, 0x65, 0x36, 0xb0, - 0xda, 0xaa, 0x48, 0xa4, 0x36, 0xb9, 0xff, 0x05, - - 0x9d, 0xff, 0x05, 0xca, 0x88, 0xd0, 0xf6, 0x20, - 0xcb, 0xbd, 0x68, 0x85, 0x36, 0xa6, 0x37, 0x98, - - 0xf0, 0x03, 0x20, 0xd1, 0x9d, 0xe0, 0x2b, 0xf0, - 0x05, 0xe0, 0x2d, 0xf0, 0x68, 0x60, 0xa8, 0xf0, - - 0xc4, 0x30, 0x38, 0x20, 0xce, 0x9d, 0xa8, 0xf0, - 0x2f, 0x30, 0x4c, 0xa0, 0x00, 0x18, 0xb1, 0x04, - - 0x65, 0x2a, 0x85, 0x2a, 0xc8, 0xb1, 0x04, 0x65, - 0x2b, 0x85, 0x2b, 0xc8, 0xb1, 0x04, 0x65, 0x2c, - - 0x85, 0x2c, 0xc8, 0xb1, 0x04, 0x65, 0x2d, 0x85, - 0x2d, 0x18, 0xa5, 0x04, 0x69, 0x04, 0x85, 0x04, - - 0xa9, 0x40, 0x90, 0xc1, 0xe6, 0x05, 0xb0, 0xbd, - 0x4c, 0x0e, 0x8c, 0x20, 0x51, 0xbd, 0x20, 0xd1, - - 0x9d, 0xa8, 0xf0, 0xf4, 0x86, 0x27, 0x30, 0x03, - 0x20, 0xbe, 0xa2, 0x20, 0x7e, 0xbd, 0x20, 0x00, - - 0xa5, 0xa6, 0x27, 0xa9, 0xff, 0xd0, 0x9e, 0x86, - 0x27, 0x20, 0xea, 0xbd, 0x20, 0x51, 0xbd, 0x20, - - 0xbe, 0xa2, 0x4c, 0x9b, 0x9c, 0xa8, 0xf0, 0xd0, - 0x30, 0x27, 0x20, 0xce, 0x9d, 0xa8, 0xf0, 0xc8, - - 0x30, 0x38, 0x38, 0xa0, 0x00, 0xb1, 0x04, 0xe5, - 0x2a, 0x85, 0x2a, 0xc8, 0xb1, 0x04, 0xe5, 0x2b, - - 0x85, 0x2b, 0xc8, 0xb1, 0x04, 0xe5, 0x2c, 0x85, - 0x2c, 0xc8, 0xb1, 0x04, 0xe5, 0x2d, 0x4c, 0x77, - - 0x9c, 0x20, 0x51, 0xbd, 0x20, 0xd1, 0x9d, 0xa8, - 0xf0, 0x9e, 0x86, 0x27, 0x30, 0x03, 0x20, 0xbe, - - 0xa2, 0x20, 0x7e, 0xbd, 0x20, 0xfd, 0xa4, 0x4c, - 0xa1, 0x9c, 0x86, 0x27, 0x20, 0xea, 0xbd, 0x20, - - 0x51, 0xbd, 0x20, 0xbe, 0xa2, 0x20, 0x7e, 0xbd, - 0x20, 0xd0, 0xa4, 0x4c, 0xa1, 0x9c, 0x20, 0xbe, - - 0xa2, 0x20, 0xea, 0xbd, 0x20, 0x51, 0xbd, 0x20, - 0xbe, 0xa2, 0x4c, 0x2c, 0x9d, 0x20, 0xbe, 0xa2, - - 0x20, 0x51, 0xbd, 0x20, 0x20, 0x9e, 0x86, 0x27, - 0xa8, 0x20, 0xfd, 0x92, 0x20, 0x7e, 0xbd, 0x20, - - 0x56, 0xa6, 0xa9, 0xff, 0xa6, 0x27, 0x4c, 0xd4, - 0x9d, 0x4c, 0x0e, 0x8c, 0xa8, 0xf0, 0xfa, 0x30, - - 0xdf, 0xa5, 0x2d, 0xc5, 0x2c, 0xd0, 0xd6, 0xa8, - 0xf0, 0x04, 0xc9, 0xff, 0xd0, 0xcf, 0x45, 0x2b, - - 0x30, 0xcb, 0x20, 0x1d, 0x9e, 0x86, 0x27, 0xa8, - 0xf0, 0xdf, 0x30, 0xb5, 0xa5, 0x2d, 0xc5, 0x2c, - - 0xd0, 0xac, 0xa8, 0xf0, 0x04, 0xc9, 0xff, 0xd0, - 0xa5, 0x45, 0x2b, 0x30, 0xa1, 0xa5, 0x2d, 0x48, - - 0x20, 0x71, 0xad, 0xa2, 0x39, 0x20, 0x44, 0xbe, - 0x20, 0xea, 0xbd, 0x68, 0x45, 0x2d, 0x85, 0x37, - - 0x20, 0x71, 0xad, 0xa0, 0x00, 0xa2, 0x00, 0x84, - 0x3f, 0x84, 0x40, 0x46, 0x3a, 0x66, 0x39, 0x90, - - 0x15, 0x18, 0x98, 0x65, 0x2a, 0xa8, 0x8a, 0x65, - 0x2b, 0xaa, 0xa5, 0x3f, 0x65, 0x2c, 0x85, 0x3f, - - 0xa5, 0x40, 0x65, 0x2d, 0x85, 0x40, 0x06, 0x2a, - 0x26, 0x2b, 0x26, 0x2c, 0x26, 0x2d, 0xa5, 0x39, - - 0x05, 0x3a, 0xd0, 0xd7, 0x84, 0x3d, 0x86, 0x3e, - 0xa5, 0x37, 0x08, 0xa2, 0x3d, 0x20, 0x56, 0xaf, - - 0x28, 0x10, 0x03, 0x20, 0x93, 0xad, 0xa6, 0x27, - 0x4c, 0xd4, 0x9d, 0x4c, 0x3c, 0x9d, 0x20, 0x94, - - 0xbd, 0x20, 0x20, 0x9e, 0xe0, 0x2a, 0xf0, 0xf3, - 0xe0, 0x2f, 0xf0, 0x09, 0xe0, 0x83, 0xf0, 0x21, - - 0xe0, 0x81, 0xf0, 0x26, 0x60, 0xa8, 0x20, 0xfd, - 0x92, 0x20, 0x51, 0xbd, 0x20, 0x20, 0x9e, 0x86, - - 0x27, 0xa8, 0x20, 0xfd, 0x92, 0x20, 0x7e, 0xbd, - 0x20, 0xad, 0xa6, 0xa6, 0x27, 0xa9, 0xff, 0xd0, - - 0xd3, 0x20, 0xbe, 0x99, 0xa5, 0x38, 0x08, 0x4c, - 0xbb, 0x9d, 0x20, 0xbe, 0x99, 0x26, 0x39, 0x26, - - 0x3a, 0x26, 0x3b, 0x26, 0x3c, 0x24, 0x37, 0x08, - 0xa2, 0x39, 0x4c, 0xbd, 0x9d, 0x20, 0x94, 0xbd, - - 0x20, 0xec, 0xad, 0x48, 0xa4, 0x1b, 0xe6, 0x1b, - 0xb1, 0x19, 0xc9, 0x20, 0xf0, 0xf6, 0xaa, 0x68, - - 0xe0, 0x5e, 0xf0, 0x01, 0x60, 0xa8, 0x20, 0xfd, - 0x92, 0x20, 0x51, 0xbd, 0x20, 0xfa, 0x92, 0xa5, - - 0x30, 0xc9, 0x87, 0xb0, 0x43, 0x20, 0x86, 0xa4, - 0xd0, 0x0f, 0x20, 0x7e, 0xbd, 0x20, 0xb5, 0xa3, - - 0xa5, 0x4a, 0x20, 0x12, 0xab, 0xa9, 0xff, 0xd0, - 0xca, 0x20, 0x81, 0xa3, 0xa5, 0x04, 0x85, 0x4b, - - 0xa5, 0x05, 0x85, 0x4c, 0x20, 0xb5, 0xa3, 0xa5, - 0x4a, 0x20, 0x12, 0xab, 0x20, 0x7d, 0xa3, 0x20, - - 0x7e, 0xbd, 0x20, 0xb5, 0xa3, 0x20, 0x01, 0xa8, - 0x20, 0xd1, 0xaa, 0x20, 0x94, 0xaa, 0x20, 0xed, - - 0xa7, 0x20, 0x56, 0xa6, 0xa9, 0xff, 0xd0, 0x9b, - 0x20, 0x81, 0xa3, 0x20, 0x99, 0xa6, 0xd0, 0xdc, - - 0x98, 0x10, 0x03, 0x20, 0xe4, 0xa3, 0xa2, 0x00, - 0xa0, 0x00, 0xb9, 0x2a, 0x00, 0x48, 0x29, 0x0f, - - 0x95, 0x3f, 0x68, 0x4a, 0x4a, 0x4a, 0x4a, 0xe8, - 0x95, 0x3f, 0xe8, 0xc8, 0xc0, 0x04, 0xd0, 0xea, - - 0xca, 0xf0, 0x04, 0xb5, 0x3f, 0xf0, 0xf9, 0xb5, - 0x3f, 0xc9, 0x0a, 0x90, 0x02, 0x69, 0x06, 0x69, - - 0x30, 0x20, 0x66, 0xa0, 0xca, 0x10, 0xf0, 0x60, - 0x10, 0x07, 0xa9, 0x2d, 0x85, 0x2e, 0x20, 0x66, - - 0xa0, 0xa5, 0x30, 0xc9, 0x81, 0xb0, 0x4e, 0x20, - 0xf4, 0xa1, 0xc6, 0x49, 0x4c, 0xd1, 0x9e, 0xae, - - 0x02, 0x04, 0xe0, 0x03, 0x90, 0x02, 0xa2, 0x00, - 0x86, 0x37, 0xad, 0x01, 0x04, 0xf0, 0x06, 0xc9, - - 0x0a, 0xb0, 0x06, 0x90, 0x06, 0xe0, 0x02, 0xf0, - 0x02, 0xa9, 0x0a, 0x85, 0x38, 0x85, 0x4e, 0xa9, - - 0x00, 0x85, 0x36, 0x85, 0x49, 0x24, 0x15, 0x30, - 0x87, 0x98, 0x30, 0x03, 0x20, 0xbe, 0xa2, 0x20, - - 0xda, 0xa1, 0xd0, 0xb4, 0xa5, 0x37, 0xd0, 0x05, - 0xa9, 0x30, 0x4c, 0x66, 0xa0, 0x4c, 0x9c, 0x9f, - - 0x20, 0x99, 0xa6, 0xd0, 0x0f, 0xc9, 0x84, 0x90, - 0x10, 0xd0, 0x06, 0xa5, 0x31, 0xc9, 0xa0, 0x90, - - 0x08, 0x20, 0x4d, 0xa2, 0xe6, 0x49, 0x4c, 0xd1, - 0x9e, 0xa5, 0x35, 0x85, 0x27, 0x20, 0x85, 0xa3, - - 0xa5, 0x4e, 0x85, 0x38, 0xa6, 0x37, 0xe0, 0x02, - 0xd0, 0x12, 0x65, 0x49, 0x30, 0x52, 0x85, 0x38, - - 0xc9, 0x0b, 0x90, 0x08, 0xa9, 0x0a, 0x85, 0x38, - 0xa9, 0x00, 0x85, 0x37, 0x20, 0x86, 0xa6, 0xa9, - - 0xa0, 0x85, 0x31, 0xa9, 0x83, 0x85, 0x30, 0xa6, - 0x38, 0xf0, 0x06, 0x20, 0x4d, 0xa2, 0xca, 0xd0, - - 0xfa, 0x20, 0xf5, 0xa7, 0x20, 0x4e, 0xa3, 0xa5, - 0x27, 0x85, 0x42, 0x20, 0x0b, 0xa5, 0xa5, 0x30, - - 0xc9, 0x84, 0xb0, 0x0e, 0x66, 0x31, 0x66, 0x32, - 0x66, 0x33, 0x66, 0x34, 0x66, 0x35, 0xe6, 0x30, - - 0xd0, 0xec, 0xa5, 0x31, 0xc9, 0xa0, 0xb0, 0x88, - 0xa5, 0x38, 0xd0, 0x11, 0xc9, 0x01, 0xf0, 0x46, - - 0x20, 0x86, 0xa6, 0xa9, 0x00, 0x85, 0x49, 0xa5, - 0x4e, 0x85, 0x38, 0xe6, 0x38, 0xa9, 0x01, 0xc5, - - 0x37, 0xf0, 0x33, 0xa4, 0x49, 0x30, 0x0c, 0xc4, - 0x38, 0xb0, 0x2b, 0xa9, 0x00, 0x85, 0x49, 0xc8, - - 0x98, 0xd0, 0x23, 0xa5, 0x37, 0xc9, 0x02, 0xf0, - 0x06, 0xa9, 0x01, 0xc0, 0xff, 0xd0, 0x17, 0xa9, - - 0x30, 0x20, 0x66, 0xa0, 0xa9, 0x2e, 0x20, 0x66, - 0xa0, 0xa9, 0x30, 0xe6, 0x49, 0xf0, 0x05, 0x20, - - 0x66, 0xa0, 0xd0, 0xf7, 0xa9, 0x80, 0x85, 0x4e, - 0x20, 0x40, 0xa0, 0xc6, 0x4e, 0xd0, 0x05, 0xa9, - - 0x2e, 0x20, 0x66, 0xa0, 0xc6, 0x38, 0xd0, 0xf0, - 0xa4, 0x37, 0x88, 0xf0, 0x18, 0x88, 0xf0, 0x11, - - 0xa4, 0x36, 0x88, 0xb9, 0x00, 0x06, 0xc9, 0x30, - 0xf0, 0xf8, 0xc9, 0x2e, 0xf0, 0x01, 0xc8, 0x84, - - 0x36, 0xa5, 0x49, 0xf0, 0x2a, 0xa9, 0x45, 0x20, - 0x66, 0xa0, 0xa5, 0x49, 0x10, 0x0a, 0xa9, 0x2d, - - 0x20, 0x66, 0xa0, 0x38, 0xa9, 0x00, 0xe5, 0x49, - 0x20, 0x52, 0xa0, 0xa5, 0x37, 0xf0, 0x10, 0xa9, - - 0x20, 0xa4, 0x49, 0x30, 0x03, 0x20, 0x66, 0xa0, - 0xe0, 0x00, 0xd0, 0x03, 0x4c, 0x66, 0xa0, 0x60, - - 0xa5, 0x31, 0x4a, 0x4a, 0x4a, 0x4a, 0x20, 0x64, - 0xa0, 0xa5, 0x31, 0x29, 0x0f, 0x85, 0x31, 0x4c, - - 0x97, 0xa1, 0xa2, 0xff, 0x38, 0xe8, 0xe9, 0x0a, - 0xb0, 0xfb, 0x69, 0x0a, 0x48, 0x8a, 0xf0, 0x03, - - 0x20, 0x64, 0xa0, 0x68, 0x09, 0x30, 0x86, 0x3b, - 0xa6, 0x36, 0x9d, 0x00, 0x06, 0xa6, 0x3b, 0xe6, - - 0x36, 0x60, 0x18, 0x86, 0x35, 0x20, 0xda, 0xa1, - 0xa9, 0xff, 0x60, 0xa2, 0x00, 0x86, 0x31, 0x86, - - 0x32, 0x86, 0x33, 0x86, 0x34, 0x86, 0x35, 0x86, - 0x48, 0x86, 0x49, 0xc9, 0x2e, 0xf0, 0x11, 0xc9, - - 0x3a, 0xb0, 0xdf, 0xe9, 0x2f, 0x30, 0xdb, 0x85, - 0x35, 0xc8, 0xb1, 0x19, 0xc9, 0x2e, 0xd0, 0x08, - - 0xa5, 0x48, 0xd0, 0x44, 0xe6, 0x48, 0xd0, 0xf1, - 0xc9, 0x45, 0xf0, 0x35, 0xc9, 0x3a, 0xb0, 0x38, - - 0xe9, 0x2f, 0x90, 0x34, 0xa6, 0x31, 0xe0, 0x18, - 0x90, 0x08, 0xa6, 0x48, 0xd0, 0xdb, 0xe6, 0x49, - - 0xb0, 0xd7, 0xa6, 0x48, 0xf0, 0x02, 0xc6, 0x49, - 0x20, 0x97, 0xa1, 0x65, 0x35, 0x85, 0x35, 0x90, - - 0xc8, 0xe6, 0x34, 0xd0, 0xc4, 0xe6, 0x33, 0xd0, - 0xc0, 0xe6, 0x32, 0xd0, 0xbc, 0xe6, 0x31, 0xd0, - - 0xb8, 0x20, 0x40, 0xa1, 0x65, 0x49, 0x85, 0x49, - 0x84, 0x1b, 0xa5, 0x49, 0x05, 0x48, 0xf0, 0x2f, - - 0x20, 0xda, 0xa1, 0xf0, 0x26, 0xa9, 0xa8, 0x85, - 0x30, 0xa9, 0x00, 0x85, 0x2f, 0x85, 0x2e, 0x20, - - 0x03, 0xa3, 0xa5, 0x49, 0x30, 0x0b, 0xf0, 0x10, - 0x20, 0xf4, 0xa1, 0xc6, 0x49, 0xd0, 0xf9, 0xf0, - - 0x07, 0x20, 0x4d, 0xa2, 0xe6, 0x49, 0xd0, 0xf9, - 0x20, 0x5c, 0xa6, 0x38, 0xa9, 0xff, 0x60, 0xa5, - - 0x32, 0x85, 0x2d, 0x29, 0x80, 0x05, 0x31, 0xd0, - 0xcc, 0xa5, 0x35, 0x85, 0x2a, 0xa5, 0x34, 0x85, - - 0x2b, 0xa5, 0x33, 0x85, 0x2c, 0xa9, 0x40, 0x38, - 0x60, 0x20, 0x4b, 0xa1, 0x49, 0xff, 0x38, 0x60, - - 0xc8, 0xb1, 0x19, 0xc9, 0x2d, 0xf0, 0xf2, 0xc9, - 0x2b, 0xd0, 0x03, 0xc8, 0xb1, 0x19, 0xc9, 0x3a, - - 0xb0, 0x22, 0xe9, 0x2f, 0x90, 0x1e, 0x85, 0x4a, - 0xc8, 0xb1, 0x19, 0xc9, 0x3a, 0xb0, 0x11, 0xe9, - - 0x2f, 0x90, 0x0d, 0xc8, 0x85, 0x43, 0xa5, 0x4a, - 0x0a, 0x0a, 0x65, 0x4a, 0x0a, 0x65, 0x43, 0x60, - - 0xa5, 0x4a, 0x18, 0x60, 0xa9, 0x00, 0x18, 0x60, - 0xa5, 0x35, 0x65, 0x42, 0x85, 0x35, 0xa5, 0x34, - - 0x65, 0x41, 0x85, 0x34, 0xa5, 0x33, 0x65, 0x40, - 0x85, 0x33, 0xa5, 0x32, 0x65, 0x3f, 0x85, 0x32, - - 0xa5, 0x31, 0x65, 0x3e, 0x85, 0x31, 0x60, 0x48, - 0xa6, 0x34, 0xa5, 0x31, 0x48, 0xa5, 0x32, 0x48, - - 0xa5, 0x33, 0x48, 0xa5, 0x35, 0x0a, 0x26, 0x34, - 0x26, 0x33, 0x26, 0x32, 0x26, 0x31, 0x0a, 0x26, - - 0x34, 0x26, 0x33, 0x26, 0x32, 0x26, 0x31, 0x65, - 0x35, 0x85, 0x35, 0x8a, 0x65, 0x34, 0x85, 0x34, - - 0x68, 0x65, 0x33, 0x85, 0x33, 0x68, 0x65, 0x32, - 0x85, 0x32, 0x68, 0x65, 0x31, 0x06, 0x35, 0x26, - - 0x34, 0x26, 0x33, 0x26, 0x32, 0x2a, 0x85, 0x31, - 0x68, 0x60, 0xa5, 0x31, 0x05, 0x32, 0x05, 0x33, - - 0x05, 0x34, 0x05, 0x35, 0xf0, 0x07, 0xa5, 0x2e, - 0xd0, 0x09, 0xa9, 0x01, 0x60, 0x85, 0x2e, 0x85, - - 0x30, 0x85, 0x2f, 0x60, 0x18, 0xa5, 0x30, 0x69, - 0x03, 0x85, 0x30, 0x90, 0x02, 0xe6, 0x2f, 0x20, - - 0x1e, 0xa2, 0x20, 0x42, 0xa2, 0x20, 0x42, 0xa2, - 0x20, 0x78, 0xa1, 0x90, 0x10, 0x66, 0x31, 0x66, - - 0x32, 0x66, 0x33, 0x66, 0x34, 0x66, 0x35, 0xe6, - 0x30, 0xd0, 0x02, 0xe6, 0x2f, 0x60, 0xa5, 0x2e, - - 0x85, 0x3b, 0xa5, 0x2f, 0x85, 0x3c, 0xa5, 0x30, - 0x85, 0x3d, 0xa5, 0x31, 0x85, 0x3e, 0xa5, 0x32, - - 0x85, 0x3f, 0xa5, 0x33, 0x85, 0x40, 0xa5, 0x34, - 0x85, 0x41, 0xa5, 0x35, 0x85, 0x42, 0x60, 0x20, - - 0x1e, 0xa2, 0x46, 0x3e, 0x66, 0x3f, 0x66, 0x40, - 0x66, 0x41, 0x66, 0x42, 0x60, 0x38, 0xa5, 0x30, - - 0xe9, 0x04, 0x85, 0x30, 0xb0, 0x02, 0xc6, 0x2f, - 0x20, 0x3f, 0xa2, 0x20, 0x08, 0xa2, 0x20, 0x3f, - - 0xa2, 0x20, 0x42, 0xa2, 0x20, 0x42, 0xa2, 0x20, - 0x42, 0xa2, 0x20, 0x08, 0xa2, 0xa9, 0x00, 0x85, - - 0x3e, 0xa5, 0x31, 0x85, 0x3f, 0xa5, 0x32, 0x85, - 0x40, 0xa5, 0x33, 0x85, 0x41, 0xa5, 0x34, 0x85, - - 0x42, 0xa5, 0x35, 0x2a, 0x20, 0x08, 0xa2, 0xa9, - 0x00, 0x85, 0x3e, 0x85, 0x3f, 0xa5, 0x31, 0x85, - - 0x40, 0xa5, 0x32, 0x85, 0x41, 0xa5, 0x33, 0x85, - 0x42, 0xa5, 0x34, 0x2a, 0x20, 0x08, 0xa2, 0xa5, - - 0x32, 0x2a, 0xa5, 0x31, 0x65, 0x35, 0x85, 0x35, - 0x90, 0x13, 0xe6, 0x34, 0xd0, 0x0f, 0xe6, 0x33, - - 0xd0, 0x0b, 0xe6, 0x32, 0xd0, 0x07, 0xe6, 0x31, - 0xd0, 0x03, 0x4c, 0x0b, 0xa2, 0x60, 0xa2, 0x00, - - 0x86, 0x35, 0x86, 0x2f, 0xa5, 0x2d, 0x10, 0x05, - 0x20, 0x93, 0xad, 0xa2, 0xff, 0x86, 0x2e, 0xa5, - - 0x2a, 0x85, 0x34, 0xa5, 0x2b, 0x85, 0x33, 0xa5, - 0x2c, 0x85, 0x32, 0xa5, 0x2d, 0x85, 0x31, 0xa9, - - 0xa0, 0x85, 0x30, 0x4c, 0x03, 0xa3, 0x85, 0x2e, - 0x85, 0x30, 0x85, 0x2f, 0x60, 0x48, 0x20, 0x86, - - 0xa6, 0x68, 0xf0, 0xf8, 0x10, 0x07, 0x85, 0x2e, - 0xa9, 0x00, 0x38, 0xe5, 0x2e, 0x85, 0x31, 0xa9, - - 0x88, 0x85, 0x30, 0xa5, 0x31, 0x30, 0xe5, 0x05, - 0x32, 0x05, 0x33, 0x05, 0x34, 0x05, 0x35, 0xf0, - - 0xd5, 0xa5, 0x30, 0xa4, 0x31, 0x30, 0xd5, 0xd0, - 0x21, 0xa6, 0x32, 0x86, 0x31, 0xa6, 0x33, 0x86, - - 0x32, 0xa6, 0x34, 0x86, 0x33, 0xa6, 0x35, 0x86, - 0x34, 0x84, 0x35, 0x38, 0xe9, 0x08, 0x85, 0x30, - - 0xb0, 0xe1, 0xc6, 0x2f, 0x90, 0xdd, 0xa4, 0x31, - 0x30, 0xb2, 0x06, 0x35, 0x26, 0x34, 0x26, 0x33, - - 0x26, 0x32, 0x26, 0x31, 0xe9, 0x00, 0x85, 0x30, - 0xb0, 0xec, 0xc6, 0x2f, 0x90, 0xe8, 0xa0, 0x04, - - 0xb1, 0x4b, 0x85, 0x41, 0x88, 0xb1, 0x4b, 0x85, - 0x40, 0x88, 0xb1, 0x4b, 0x85, 0x3f, 0x88, 0xb1, - - 0x4b, 0x85, 0x3b, 0x88, 0x84, 0x42, 0x84, 0x3c, - 0xb1, 0x4b, 0x85, 0x3d, 0x05, 0x3b, 0x05, 0x3f, - - 0x05, 0x40, 0x05, 0x41, 0xf0, 0x04, 0xa5, 0x3b, - 0x09, 0x80, 0x85, 0x3e, 0x60, 0xa9, 0x71, 0xd0, - - 0x06, 0xa9, 0x76, 0xd0, 0x02, 0xa9, 0x6c, 0x85, - 0x4b, 0xa9, 0x04, 0x85, 0x4c, 0xa0, 0x00, 0xa5, - - 0x30, 0x91, 0x4b, 0xc8, 0xa5, 0x2e, 0x29, 0x80, - 0x85, 0x2e, 0xa5, 0x31, 0x29, 0x7f, 0x05, 0x2e, - - 0x91, 0x4b, 0xa5, 0x32, 0xc8, 0x91, 0x4b, 0xa5, - 0x33, 0xc8, 0x91, 0x4b, 0xa5, 0x34, 0xc8, 0x91, - - 0x4b, 0x60, 0x20, 0xf5, 0xa7, 0xa0, 0x04, 0xb1, - 0x4b, 0x85, 0x34, 0x88, 0xb1, 0x4b, 0x85, 0x33, - - 0x88, 0xb1, 0x4b, 0x85, 0x32, 0x88, 0xb1, 0x4b, - 0x85, 0x2e, 0x88, 0xb1, 0x4b, 0x85, 0x30, 0x84, - - 0x35, 0x84, 0x2f, 0x05, 0x2e, 0x05, 0x32, 0x05, - 0x33, 0x05, 0x34, 0xf0, 0x04, 0xa5, 0x2e, 0x09, - - 0x80, 0x85, 0x31, 0x60, 0x20, 0xfe, 0xa3, 0xa5, - 0x31, 0x85, 0x2d, 0xa5, 0x32, 0x85, 0x2c, 0xa5, - - 0x33, 0x85, 0x2b, 0xa5, 0x34, 0x85, 0x2a, 0x60, - 0x20, 0x1e, 0xa2, 0x4c, 0x86, 0xa6, 0xa5, 0x30, - - 0x10, 0xf6, 0x20, 0x53, 0xa4, 0x20, 0xda, 0xa1, - 0xd0, 0x32, 0xf0, 0x5c, 0xa5, 0x30, 0xc9, 0xa0, - - 0xb0, 0x54, 0xc9, 0x99, 0xb0, 0x26, 0x69, 0x08, - 0x85, 0x30, 0xa5, 0x40, 0x85, 0x41, 0xa5, 0x3f, - - 0x85, 0x40, 0xa5, 0x3e, 0x85, 0x3f, 0xa5, 0x34, - 0x85, 0x3e, 0xa5, 0x33, 0x85, 0x34, 0xa5, 0x32, - - 0x85, 0x33, 0xa5, 0x31, 0x85, 0x32, 0xa9, 0x00, - 0x85, 0x31, 0xf0, 0xd0, 0x46, 0x31, 0x66, 0x32, - - 0x66, 0x33, 0x66, 0x34, 0x66, 0x3e, 0x66, 0x3f, - 0x66, 0x40, 0x66, 0x41, 0xe6, 0x30, 0xd0, 0xbc, - - 0x4c, 0x6c, 0xa6, 0xa9, 0x00, 0x85, 0x3b, 0x85, - 0x3c, 0x85, 0x3d, 0x85, 0x3e, 0x85, 0x3f, 0x85, - - 0x40, 0x85, 0x41, 0x85, 0x42, 0x60, 0xd0, 0xe8, - 0xa5, 0x2e, 0x10, 0x19, 0x38, 0xa9, 0x00, 0xe5, - - 0x34, 0x85, 0x34, 0xa9, 0x00, 0xe5, 0x33, 0x85, - 0x33, 0xa9, 0x00, 0xe5, 0x32, 0x85, 0x32, 0xa9, - - 0x00, 0xe5, 0x31, 0x85, 0x31, 0x60, 0xa5, 0x30, - 0x30, 0x07, 0xa9, 0x00, 0x85, 0x4a, 0x4c, 0xda, - - 0xa1, 0x20, 0xfe, 0xa3, 0xa5, 0x34, 0x85, 0x4a, - 0x20, 0xe8, 0xa4, 0xa9, 0x80, 0x85, 0x30, 0xa6, - - 0x31, 0x10, 0x10, 0x45, 0x2e, 0x85, 0x2e, 0x10, - 0x05, 0xe6, 0x4a, 0x4c, 0xb0, 0xa4, 0xc6, 0x4a, - - 0x20, 0x6c, 0xa4, 0x4c, 0x03, 0xa3, 0xe6, 0x34, - 0xd0, 0x0c, 0xe6, 0x33, 0xd0, 0x08, 0xe6, 0x32, - - 0xd0, 0x04, 0xe6, 0x31, 0xf0, 0x8a, 0x60, 0x20, - 0x6c, 0xa4, 0x20, 0xb6, 0xa4, 0x4c, 0x6c, 0xa4, - - 0x20, 0xfd, 0xa4, 0x4c, 0x7e, 0xad, 0x20, 0x4e, - 0xa3, 0x20, 0x8d, 0xa3, 0xa5, 0x3b, 0x85, 0x2e, - - 0xa5, 0x3c, 0x85, 0x2f, 0xa5, 0x3d, 0x85, 0x30, - 0xa5, 0x3e, 0x85, 0x31, 0xa5, 0x3f, 0x85, 0x32, - - 0xa5, 0x40, 0x85, 0x33, 0xa5, 0x41, 0x85, 0x34, - 0xa5, 0x42, 0x85, 0x35, 0x60, 0x20, 0x7e, 0xad, - - 0x20, 0x4e, 0xa3, 0xf0, 0xf7, 0x20, 0x0b, 0xa5, - 0x4c, 0x5c, 0xa6, 0x20, 0xda, 0xa1, 0xf0, 0xcc, - - 0xa0, 0x00, 0x38, 0xa5, 0x30, 0xe5, 0x3d, 0xf0, - 0x77, 0x90, 0x37, 0xc9, 0x25, 0xb0, 0xdd, 0x48, - - 0x29, 0x38, 0xf0, 0x19, 0x4a, 0x4a, 0x4a, 0xaa, - 0xa5, 0x41, 0x85, 0x42, 0xa5, 0x40, 0x85, 0x41, - - 0xa5, 0x3f, 0x85, 0x40, 0xa5, 0x3e, 0x85, 0x3f, - 0x84, 0x3e, 0xca, 0xd0, 0xeb, 0x68, 0x29, 0x07, - - 0xf0, 0x4e, 0xaa, 0x46, 0x3e, 0x66, 0x3f, 0x66, - 0x40, 0x66, 0x41, 0x66, 0x42, 0xca, 0xd0, 0xf3, - - 0xf0, 0x3e, 0x38, 0xa5, 0x3d, 0xe5, 0x30, 0xc9, - 0x25, 0xb0, 0x81, 0x48, 0x29, 0x38, 0xf0, 0x19, - - 0x4a, 0x4a, 0x4a, 0xaa, 0xa5, 0x34, 0x85, 0x35, - 0xa5, 0x33, 0x85, 0x34, 0xa5, 0x32, 0x85, 0x33, - - 0xa5, 0x31, 0x85, 0x32, 0x84, 0x31, 0xca, 0xd0, - 0xeb, 0x68, 0x29, 0x07, 0xf0, 0x0e, 0xaa, 0x46, - - 0x31, 0x66, 0x32, 0x66, 0x33, 0x66, 0x34, 0x66, - 0x35, 0xca, 0xd0, 0xf3, 0xa5, 0x3d, 0x85, 0x30, - - 0xa5, 0x2e, 0x45, 0x3b, 0x10, 0x49, 0xa5, 0x31, - 0xc5, 0x3e, 0xd0, 0x1b, 0xa5, 0x32, 0xc5, 0x3f, - - 0xd0, 0x15, 0xa5, 0x33, 0xc5, 0x40, 0xd0, 0x0f, - 0xa5, 0x34, 0xc5, 0x41, 0xd0, 0x09, 0xa5, 0x35, - - 0xc5, 0x42, 0xd0, 0x03, 0x4c, 0x86, 0xa6, 0xb0, - 0x2a, 0x38, 0xa5, 0x42, 0xe5, 0x35, 0x85, 0x35, - - 0xa5, 0x41, 0xe5, 0x34, 0x85, 0x34, 0xa5, 0x40, - 0xe5, 0x33, 0x85, 0x33, 0xa5, 0x3f, 0xe5, 0x32, - - 0x85, 0x32, 0xa5, 0x3e, 0xe5, 0x31, 0x85, 0x31, - 0xa5, 0x3b, 0x85, 0x2e, 0x4c, 0x03, 0xa3, 0x18, - - 0x4c, 0x08, 0xa2, 0x38, 0xa5, 0x35, 0xe5, 0x42, - 0x85, 0x35, 0xa5, 0x34, 0xe5, 0x41, 0x85, 0x34, - - 0xa5, 0x33, 0xe5, 0x40, 0x85, 0x33, 0xa5, 0x32, - 0xe5, 0x3f, 0x85, 0x32, 0xa5, 0x31, 0xe5, 0x3e, - - 0x85, 0x31, 0x4c, 0x03, 0xa3, 0x60, 0x20, 0xda, - 0xa1, 0xf0, 0xfa, 0x20, 0x4e, 0xa3, 0xd0, 0x03, - - 0x4c, 0x86, 0xa6, 0x18, 0xa5, 0x30, 0x65, 0x3d, - 0x90, 0x03, 0xe6, 0x2f, 0x18, 0xe9, 0x7f, 0x85, - - 0x30, 0xb0, 0x02, 0xc6, 0x2f, 0xa2, 0x05, 0xa0, - 0x00, 0xb5, 0x30, 0x95, 0x42, 0x94, 0x30, 0xca, - - 0xd0, 0xf7, 0xa5, 0x2e, 0x45, 0x3b, 0x85, 0x2e, - 0xa0, 0x20, 0x46, 0x3e, 0x66, 0x3f, 0x66, 0x40, - - 0x66, 0x41, 0x66, 0x42, 0x06, 0x46, 0x26, 0x45, - 0x26, 0x44, 0x26, 0x43, 0x90, 0x04, 0x18, 0x20, - - 0x78, 0xa1, 0x88, 0xd0, 0xe5, 0x60, 0x20, 0x06, - 0xa6, 0x20, 0x03, 0xa3, 0xa5, 0x35, 0xc9, 0x80, - - 0x90, 0x1a, 0xf0, 0x12, 0xa9, 0xff, 0x20, 0xa4, - 0xa2, 0x4c, 0x7c, 0xa6, 0x00, 0x14, 0x54, 0x6f, - - 0x6f, 0x20, 0x62, 0x69, 0x67, 0x00, 0xa5, 0x34, - 0x09, 0x01, 0x85, 0x34, 0xa9, 0x00, 0x85, 0x35, - - 0xa5, 0x2f, 0xf0, 0x14, 0x10, 0xe6, 0xa9, 0x00, - 0x85, 0x2e, 0x85, 0x2f, 0x85, 0x30, 0x85, 0x31, - - 0x85, 0x32, 0x85, 0x33, 0x85, 0x34, 0x85, 0x35, - 0x60, 0x20, 0x86, 0xa6, 0xa0, 0x80, 0x84, 0x31, - - 0xc8, 0x84, 0x30, 0x98, 0x60, 0x20, 0x85, 0xa3, - 0x20, 0x99, 0xa6, 0xd0, 0x3a, 0x20, 0xda, 0xa1, - - 0xf0, 0x09, 0x20, 0x1e, 0xa2, 0x20, 0xb5, 0xa3, - 0xd0, 0x37, 0x60, 0x4c, 0xa7, 0x99, 0x20, 0xfa, - - 0x92, 0x20, 0xd3, 0xa9, 0xa5, 0x4a, 0x48, 0x20, - 0xe9, 0xa7, 0x20, 0x8d, 0xa3, 0xe6, 0x4a, 0x20, - - 0x9e, 0xa9, 0x20, 0xe9, 0xa7, 0x20, 0xd6, 0xa4, - 0x68, 0x85, 0x4a, 0x20, 0x9e, 0xa9, 0x20, 0xe9, - - 0xa7, 0x20, 0xe7, 0xa6, 0xa9, 0xff, 0x60, 0x20, - 0xda, 0xa1, 0xf0, 0xac, 0x20, 0x4e, 0xa3, 0xf0, - - 0xca, 0xa5, 0x2e, 0x45, 0x3b, 0x85, 0x2e, 0x38, - 0xa5, 0x30, 0xe5, 0x3d, 0xb0, 0x03, 0xc6, 0x2f, - - 0x38, 0x69, 0x80, 0x85, 0x30, 0x90, 0x03, 0xe6, - 0x2f, 0x18, 0xa2, 0x20, 0xb0, 0x18, 0xa5, 0x31, - - 0xc5, 0x3e, 0xd0, 0x10, 0xa5, 0x32, 0xc5, 0x3f, - 0xd0, 0x0a, 0xa5, 0x33, 0xc5, 0x40, 0xd0, 0x04, - - 0xa5, 0x34, 0xc5, 0x41, 0x90, 0x19, 0xa5, 0x34, - 0xe5, 0x41, 0x85, 0x34, 0xa5, 0x33, 0xe5, 0x40, - - 0x85, 0x33, 0xa5, 0x32, 0xe5, 0x3f, 0x85, 0x32, - 0xa5, 0x31, 0xe5, 0x3e, 0x85, 0x31, 0x38, 0x26, - - 0x46, 0x26, 0x45, 0x26, 0x44, 0x26, 0x43, 0x06, - 0x34, 0x26, 0x33, 0x26, 0x32, 0x26, 0x31, 0xca, - - 0xd0, 0xba, 0xa2, 0x07, 0xb0, 0x18, 0xa5, 0x31, - 0xc5, 0x3e, 0xd0, 0x10, 0xa5, 0x32, 0xc5, 0x3f, - - 0xd0, 0x0a, 0xa5, 0x33, 0xc5, 0x40, 0xd0, 0x04, - 0xa5, 0x34, 0xc5, 0x41, 0x90, 0x19, 0xa5, 0x34, - - 0xe5, 0x41, 0x85, 0x34, 0xa5, 0x33, 0xe5, 0x40, - 0x85, 0x33, 0xa5, 0x32, 0xe5, 0x3f, 0x85, 0x32, - - 0xa5, 0x31, 0xe5, 0x3e, 0x85, 0x31, 0x38, 0x26, - 0x35, 0x06, 0x34, 0x26, 0x33, 0x26, 0x32, 0x26, - - 0x31, 0xca, 0xd0, 0xc0, 0x06, 0x35, 0xa5, 0x46, - 0x85, 0x34, 0xa5, 0x45, 0x85, 0x33, 0xa5, 0x44, - - 0x85, 0x32, 0xa5, 0x43, 0x85, 0x31, 0x4c, 0x59, - 0xa6, 0x00, 0x15, 0x2d, 0x76, 0x65, 0x20, 0x72, - - 0x6f, 0x6f, 0x74, 0x00, 0x20, 0xfa, 0x92, 0x20, - 0xda, 0xa1, 0xf0, 0x2a, 0x30, 0xeb, 0x20, 0x85, - - 0xa3, 0xa5, 0x30, 0x4a, 0x69, 0x40, 0x85, 0x30, - 0xa9, 0x05, 0x85, 0x4a, 0x20, 0xed, 0xa7, 0x20, - - 0x8d, 0xa3, 0xa9, 0x6c, 0x85, 0x4b, 0x20, 0xad, - 0xa6, 0xa9, 0x71, 0x85, 0x4b, 0x20, 0x00, 0xa5, - - 0xc6, 0x30, 0xc6, 0x4a, 0xd0, 0xe9, 0xa9, 0xff, - 0x60, 0xa9, 0x7b, 0xd0, 0x0a, 0xa9, 0x71, 0xd0, - - 0x06, 0xa9, 0x76, 0xd0, 0x02, 0xa9, 0x6c, 0x85, - 0x4b, 0xa9, 0x04, 0x85, 0x4c, 0x60, 0x20, 0xfa, - - 0x92, 0x20, 0xda, 0xa1, 0xf0, 0x02, 0x10, 0x0c, - 0x00, 0x16, 0x4c, 0x6f, 0x67, 0x20, 0x72, 0x61, - - 0x6e, 0x67, 0x65, 0x00, 0x20, 0x53, 0xa4, 0xa0, - 0x80, 0x84, 0x3b, 0x84, 0x3e, 0xc8, 0x84, 0x3d, - - 0xa6, 0x30, 0xf0, 0x06, 0xa5, 0x31, 0xc9, 0xb5, - 0x90, 0x02, 0xe8, 0x88, 0x8a, 0x48, 0x84, 0x30, - - 0x20, 0x05, 0xa5, 0xa9, 0x7b, 0x20, 0x87, 0xa3, - 0xa9, 0x73, 0xa0, 0xa8, 0x20, 0x97, 0xa8, 0x20, - - 0xe9, 0xa7, 0x20, 0x56, 0xa6, 0x20, 0x56, 0xa6, - 0x20, 0x00, 0xa5, 0x20, 0x85, 0xa3, 0x68, 0x38, - - 0xe9, 0x81, 0x20, 0xed, 0xa2, 0xa9, 0x6e, 0x85, - 0x4b, 0xa9, 0xa8, 0x85, 0x4c, 0x20, 0x56, 0xa6, - - 0x20, 0xf5, 0xa7, 0x20, 0x00, 0xa5, 0xa9, 0xff, - 0x60, 0x7f, 0x5e, 0x5b, 0xd8, 0xaa, 0x80, 0x31, - - 0x72, 0x17, 0xf8, 0x06, 0x7a, 0x12, 0x38, 0xa5, - 0x0b, 0x88, 0x79, 0x0e, 0x9f, 0xf3, 0x7c, 0x2a, - - 0xac, 0x3f, 0xb5, 0x86, 0x34, 0x01, 0xa2, 0x7a, - 0x7f, 0x63, 0x8e, 0x37, 0xec, 0x82, 0x3f, 0xff, - - 0xff, 0xc1, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x85, - 0x4d, 0x84, 0x4e, 0x20, 0x85, 0xa3, 0xa0, 0x00, - - 0xb1, 0x4d, 0x85, 0x48, 0xe6, 0x4d, 0xd0, 0x02, - 0xe6, 0x4e, 0xa5, 0x4d, 0x85, 0x4b, 0xa5, 0x4e, - - 0x85, 0x4c, 0x20, 0xb5, 0xa3, 0x20, 0xf5, 0xa7, - 0x20, 0xad, 0xa6, 0x18, 0xa5, 0x4d, 0x69, 0x05, - - 0x85, 0x4d, 0x85, 0x4b, 0xa5, 0x4e, 0x69, 0x00, - 0x85, 0x4e, 0x85, 0x4c, 0x20, 0x00, 0xa5, 0xc6, - - 0x48, 0xd0, 0xe2, 0x60, 0x20, 0xda, 0xa8, 0x4c, - 0x27, 0xa9, 0x20, 0xfa, 0x92, 0x20, 0xda, 0xa1, - - 0x10, 0x08, 0x46, 0x2e, 0x20, 0xea, 0xa8, 0x4c, - 0x16, 0xa9, 0x20, 0x81, 0xa3, 0x20, 0xb1, 0xa9, - - 0x20, 0xda, 0xa1, 0xf0, 0x09, 0x20, 0xf1, 0xa7, - 0x20, 0xad, 0xa6, 0x4c, 0x0a, 0xa9, 0x20, 0x55, - - 0xaa, 0x20, 0xb5, 0xa3, 0xa9, 0xff, 0x60, 0x20, - 0xfa, 0x92, 0x20, 0xda, 0xa1, 0xf0, 0xf5, 0x10, - - 0x0a, 0x46, 0x2e, 0x20, 0x1b, 0xa9, 0xa9, 0x80, - 0x85, 0x2e, 0x60, 0xa5, 0x30, 0xc9, 0x81, 0x90, - - 0x15, 0x20, 0xa5, 0xa6, 0x20, 0x36, 0xa9, 0x20, - 0x48, 0xaa, 0x20, 0x00, 0xa5, 0x20, 0x4c, 0xaa, - - 0x20, 0x00, 0xa5, 0x4c, 0x7e, 0xad, 0xa5, 0x30, - 0xc9, 0x73, 0x90, 0xc8, 0x20, 0x81, 0xa3, 0x20, - - 0x53, 0xa4, 0xa9, 0x80, 0x85, 0x3d, 0x85, 0x3e, - 0x85, 0x3b, 0x20, 0x05, 0xa5, 0xa9, 0x5a, 0xa0, - - 0xa9, 0x20, 0x97, 0xa8, 0x20, 0xd1, 0xaa, 0xa9, - 0xff, 0x60, 0x09, 0x85, 0xa3, 0x59, 0xe8, 0x67, - - 0x80, 0x1c, 0x9d, 0x07, 0x36, 0x80, 0x57, 0xbb, - 0x78, 0xdf, 0x80, 0xca, 0x9a, 0x0e, 0x83, 0x84, - - 0x8c, 0xbb, 0xca, 0x6e, 0x81, 0x95, 0x96, 0x06, - 0xde, 0x81, 0x0a, 0xc7, 0x6c, 0x52, 0x7f, 0x7d, - - 0xad, 0x90, 0xa1, 0x82, 0xfb, 0x62, 0x57, 0x2f, - 0x80, 0x6d, 0x63, 0x38, 0x2c, 0x20, 0xfa, 0x92, - - 0x20, 0xd3, 0xa9, 0xe6, 0x4a, 0x4c, 0x9e, 0xa9, - 0x20, 0xfa, 0x92, 0x20, 0xd3, 0xa9, 0xa5, 0x4a, - - 0x29, 0x02, 0xf0, 0x06, 0x20, 0xaa, 0xa9, 0x4c, - 0x7e, 0xad, 0x46, 0x4a, 0x90, 0x15, 0x20, 0xc3, - - 0xa9, 0x20, 0x85, 0xa3, 0x20, 0x56, 0xa6, 0x20, - 0x8d, 0xa3, 0x20, 0x99, 0xa6, 0x20, 0xd0, 0xa4, - - 0x4c, 0xb7, 0xa7, 0x20, 0x81, 0xa3, 0x20, 0x56, - 0xa6, 0xa9, 0x72, 0xa0, 0xaa, 0x20, 0x97, 0xa8, - - 0x4c, 0xd1, 0xaa, 0xa5, 0x30, 0xc9, 0x98, 0xb0, - 0x5f, 0x20, 0x85, 0xa3, 0x20, 0x55, 0xaa, 0x20, - - 0x4e, 0xa3, 0xa5, 0x2e, 0x85, 0x3b, 0xc6, 0x3d, - 0x20, 0x05, 0xa5, 0x20, 0xe7, 0xa6, 0x20, 0xfe, - - 0xa3, 0xa5, 0x34, 0x85, 0x4a, 0x05, 0x33, 0x05, - 0x32, 0x05, 0x31, 0xf0, 0x38, 0xa9, 0xa0, 0x85, - - 0x30, 0xa0, 0x00, 0x84, 0x35, 0xa5, 0x31, 0x85, - 0x2e, 0x10, 0x03, 0x20, 0x6c, 0xa4, 0x20, 0x03, - - 0xa3, 0x20, 0x7d, 0xa3, 0x20, 0x48, 0xaa, 0x20, - 0x56, 0xa6, 0x20, 0xf5, 0xa7, 0x20, 0x00, 0xa5, - - 0x20, 0x8d, 0xa3, 0x20, 0xed, 0xa7, 0x20, 0xb5, - 0xa3, 0x20, 0x4c, 0xaa, 0x20, 0x56, 0xa6, 0x20, - - 0xf5, 0xa7, 0x4c, 0x00, 0xa5, 0x4c, 0xb2, 0xa3, - 0x00, 0x17, 0x41, 0x63, 0x63, 0x75, 0x72, 0x61, - - 0x63, 0x79, 0x20, 0x6c, 0x6f, 0x73, 0x74, 0x00, - 0xa9, 0x59, 0xd0, 0x02, 0xa9, 0x5e, 0x85, 0x4b, - - 0xa9, 0xaa, 0x85, 0x4c, 0x60, 0xa9, 0x63, 0xd0, - 0xf5, 0x81, 0xc9, 0x10, 0x00, 0x00, 0x6f, 0x15, - - 0x77, 0x7a, 0x61, 0x81, 0x49, 0x0f, 0xda, 0xa2, - 0x7b, 0x0e, 0xfa, 0x35, 0x12, 0x86, 0x65, 0x2e, - - 0xe0, 0xd3, 0x05, 0x84, 0x8a, 0xea, 0x0c, 0x1b, - 0x84, 0x1a, 0xbe, 0xbb, 0x2b, 0x84, 0x37, 0x45, - - 0x55, 0xab, 0x82, 0xd5, 0x55, 0x57, 0x7c, 0x83, - 0xc0, 0x00, 0x00, 0x05, 0x81, 0x00, 0x00, 0x00, - - 0x00, 0x20, 0xfa, 0x92, 0xa5, 0x30, 0xc9, 0x87, - 0x90, 0x1e, 0xd0, 0x06, 0xa4, 0x31, 0xc0, 0xb3, - - 0x90, 0x16, 0xa5, 0x2e, 0x10, 0x06, 0x20, 0x86, - 0xa6, 0xa9, 0xff, 0x60, 0x00, 0x18, 0x45, 0x78, - - 0x70, 0x20, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x00, - 0x20, 0x86, 0xa4, 0x20, 0xda, 0xaa, 0x20, 0x81, - - 0xa3, 0xa9, 0xe4, 0x85, 0x4b, 0xa9, 0xaa, 0x85, - 0x4c, 0x20, 0xb5, 0xa3, 0xa5, 0x4a, 0x20, 0x12, - - 0xab, 0x20, 0xf1, 0xa7, 0x20, 0x56, 0xa6, 0xa9, - 0xff, 0x60, 0xa9, 0xe9, 0xa0, 0xaa, 0x20, 0x97, - - 0xa8, 0xa9, 0xff, 0x60, 0x82, 0x2d, 0xf8, 0x54, - 0x58, 0x07, 0x83, 0xe0, 0x20, 0x86, 0x5b, 0x82, - - 0x80, 0x53, 0x93, 0xb8, 0x83, 0x20, 0x00, 0x06, - 0xa1, 0x82, 0x00, 0x00, 0x21, 0x63, 0x82, 0xc0, - - 0x00, 0x00, 0x02, 0x82, 0x80, 0x00, 0x00, 0x0c, - 0x81, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, - - 0x00, 0x00, 0xaa, 0x10, 0x09, 0xca, 0x8a, 0x49, - 0xff, 0x48, 0x20, 0xa5, 0xa6, 0x68, 0x48, 0x20, - - 0x85, 0xa3, 0x20, 0x99, 0xa6, 0x68, 0xf0, 0x0a, - 0x38, 0xe9, 0x01, 0x48, 0x20, 0x56, 0xa6, 0x4c, - - 0x25, 0xab, 0x60, 0x20, 0xe3, 0x92, 0xa6, 0x2a, - 0xa9, 0x80, 0x20, 0xf4, 0xff, 0x8a, 0x4c, 0xea, - - 0xae, 0x20, 0xdd, 0x92, 0x20, 0x94, 0xbd, 0x20, - 0xae, 0x8a, 0x20, 0x56, 0xae, 0x20, 0xf0, 0x92, - - 0xa5, 0x2a, 0x48, 0xa5, 0x2b, 0x48, 0x20, 0xea, - 0xbd, 0x68, 0x85, 0x2d, 0x68, 0x85, 0x2c, 0xa2, - - 0x2a, 0xa9, 0x09, 0x20, 0xf1, 0xff, 0xa5, 0x2e, - 0x30, 0x33, 0x4c, 0xd8, 0xae, 0xa9, 0x86, 0x20, - - 0xf4, 0xff, 0x8a, 0x4c, 0xd8, 0xae, 0xa9, 0x86, - 0x20, 0xf4, 0xff, 0x98, 0x4c, 0xd8, 0xae, 0x20, - - 0xda, 0xa1, 0xf0, 0x1e, 0x10, 0x1a, 0x30, 0x15, - 0x20, 0xec, 0xad, 0xf0, 0x59, 0x30, 0xf0, 0xa5, - - 0x2d, 0x05, 0x2c, 0x05, 0x2b, 0x05, 0x2a, 0xf0, - 0x0c, 0xa5, 0x2d, 0x10, 0x03, 0x4c, 0xc4, 0xac, - - 0xa9, 0x01, 0x4c, 0xd8, 0xae, 0xa9, 0x40, 0x60, - 0x20, 0xfe, 0xa7, 0xa0, 0x69, 0xa9, 0xa8, 0xd0, - - 0x07, 0x20, 0xfa, 0x92, 0xa0, 0x68, 0xa9, 0xaa, - 0x84, 0x4b, 0x85, 0x4c, 0x20, 0x56, 0xa6, 0xa9, - - 0xff, 0x60, 0x20, 0xfa, 0x92, 0xa0, 0x6d, 0xa9, - 0xaa, 0xd0, 0xed, 0x20, 0xfe, 0xa8, 0xe6, 0x30, - - 0xa8, 0x60, 0x20, 0xe3, 0x92, 0x20, 0x1e, 0x8f, - 0x85, 0x2a, 0x86, 0x2b, 0x84, 0x2c, 0x08, 0x68, - - 0x85, 0x2d, 0xd8, 0xa9, 0x40, 0x60, 0x4c, 0x0e, - 0x8c, 0x20, 0xec, 0xad, 0xd0, 0xf8, 0xe6, 0x36, - - 0xa4, 0x36, 0xa9, 0x0d, 0x99, 0xff, 0x05, 0x20, - 0xb2, 0xbd, 0xa5, 0x19, 0x48, 0xa5, 0x1a, 0x48, - - 0xa5, 0x1b, 0x48, 0xa4, 0x04, 0xa6, 0x05, 0xc8, - 0x84, 0x19, 0x84, 0x37, 0xd0, 0x01, 0xe8, 0x86, - - 0x1a, 0x86, 0x38, 0xa0, 0xff, 0x84, 0x3b, 0xc8, - 0x84, 0x1b, 0x20, 0x55, 0x89, 0x20, 0x29, 0x9b, - - 0x20, 0xdc, 0xbd, 0x68, 0x85, 0x1b, 0x68, 0x85, - 0x1a, 0x68, 0x85, 0x19, 0xa5, 0x27, 0x60, 0x20, - - 0xec, 0xad, 0xd0, 0x67, 0xa4, 0x36, 0xa9, 0x00, - 0x99, 0x00, 0x06, 0xa5, 0x19, 0x48, 0xa5, 0x1a, - - 0x48, 0xa5, 0x1b, 0x48, 0xa9, 0x00, 0x85, 0x1b, - 0xa9, 0x00, 0x85, 0x19, 0xa9, 0x06, 0x85, 0x1a, - - 0x20, 0x8c, 0x8a, 0xc9, 0x2d, 0xf0, 0x0f, 0xc9, - 0x2b, 0xd0, 0x03, 0x20, 0x8c, 0x8a, 0xc6, 0x1b, - - 0x20, 0x7b, 0xa0, 0x4c, 0x73, 0xac, 0x20, 0x8c, - 0x8a, 0xc6, 0x1b, 0x20, 0x7b, 0xa0, 0x90, 0x03, - - 0x20, 0x8f, 0xad, 0x85, 0x27, 0x4c, 0x23, 0xac, - 0x20, 0xec, 0xad, 0xf0, 0x1e, 0x10, 0x1b, 0xa5, - - 0x2e, 0x08, 0x20, 0xfe, 0xa3, 0x28, 0x10, 0x0d, - 0xa5, 0x3e, 0x05, 0x3f, 0x05, 0x40, 0x05, 0x41, - - 0xf0, 0x03, 0x20, 0xc7, 0xa4, 0x20, 0xe7, 0xa3, - 0xa9, 0x40, 0x60, 0x4c, 0x0e, 0x8c, 0x20, 0xec, - - 0xad, 0xd0, 0xf8, 0xa5, 0x36, 0xf0, 0x1d, 0xad, - 0x00, 0x06, 0x4c, 0xd8, 0xae, 0x20, 0xad, 0xaf, - - 0xc0, 0x00, 0xd0, 0x10, 0x8a, 0x4c, 0xea, 0xae, - 0x20, 0xb5, 0xbf, 0xaa, 0xa9, 0x7f, 0x20, 0xf4, - - 0xff, 0x8a, 0xf0, 0xe6, 0xa9, 0xff, 0x85, 0x2a, - 0x85, 0x2b, 0x85, 0x2c, 0x85, 0x2d, 0xa9, 0x40, - - 0x60, 0x20, 0xe3, 0x92, 0xa2, 0x03, 0xb5, 0x2a, - 0x49, 0xff, 0x95, 0x2a, 0xca, 0x10, 0xf7, 0xa9, - - 0x40, 0x60, 0x20, 0x29, 0x9b, 0xd0, 0xb4, 0xe0, - 0x2c, 0xd0, 0x18, 0xe6, 0x1b, 0x20, 0xb2, 0xbd, - - 0x20, 0x29, 0x9b, 0xd0, 0xa6, 0xa9, 0x01, 0x85, - 0x2a, 0xe6, 0x1b, 0xe0, 0x29, 0xf0, 0x13, 0xe0, - - 0x2c, 0xf0, 0x03, 0x4c, 0xa2, 0x8a, 0x20, 0xb2, - 0xbd, 0x20, 0x56, 0xae, 0x20, 0xf0, 0x92, 0x20, - - 0xcb, 0xbd, 0xa0, 0x00, 0xa6, 0x2a, 0xd0, 0x02, - 0xa2, 0x01, 0x86, 0x2a, 0x8a, 0xca, 0x86, 0x2d, - - 0x18, 0x65, 0x04, 0x85, 0x37, 0x98, 0x65, 0x05, - 0x85, 0x38, 0xb1, 0x04, 0x38, 0xe5, 0x2d, 0x90, - - 0x21, 0xe5, 0x36, 0x90, 0x1d, 0x69, 0x00, 0x85, - 0x2b, 0x20, 0xdc, 0xbd, 0xa0, 0x00, 0xa6, 0x36, - - 0xf0, 0x0b, 0xb1, 0x37, 0xd9, 0x00, 0x06, 0xd0, - 0x10, 0xc8, 0xca, 0xd0, 0xf5, 0xa5, 0x2a, 0x4c, - - 0xd8, 0xae, 0x20, 0xdc, 0xbd, 0xa9, 0x00, 0xf0, - 0xf6, 0xe6, 0x2a, 0xc6, 0x2b, 0xf0, 0xf6, 0xe6, - - 0x37, 0xd0, 0xd9, 0xe6, 0x38, 0xd0, 0xd5, 0x4c, - 0x0e, 0x8c, 0x20, 0xec, 0xad, 0xf0, 0xf8, 0x30, - - 0x06, 0x24, 0x2d, 0x30, 0x1e, 0x10, 0x33, 0x20, - 0xda, 0xa1, 0x10, 0x0d, 0x30, 0x05, 0x20, 0xda, - - 0xa1, 0xf0, 0x06, 0xa5, 0x2e, 0x49, 0x80, 0x85, - 0x2e, 0xa9, 0xff, 0x60, 0x20, 0x02, 0xae, 0xf0, - - 0xd6, 0x30, 0xeb, 0x38, 0xa9, 0x00, 0xa8, 0xe5, - 0x2a, 0x85, 0x2a, 0x98, 0xe5, 0x2b, 0x85, 0x2b, - - 0x98, 0xe5, 0x2c, 0x85, 0x2c, 0x98, 0xe5, 0x2d, - 0x85, 0x2d, 0xa9, 0x40, 0x60, 0x20, 0x8c, 0x8a, - - 0xc9, 0x22, 0xf0, 0x15, 0xa2, 0x00, 0xb1, 0x19, - 0x9d, 0x00, 0x06, 0xc8, 0xe8, 0xc9, 0x0d, 0xf0, - - 0x04, 0xc9, 0x2c, 0xd0, 0xf1, 0x88, 0x4c, 0xe1, - 0xad, 0xa2, 0x00, 0xc8, 0xb1, 0x19, 0xc9, 0x0d, - - 0xf0, 0x17, 0xc8, 0x9d, 0x00, 0x06, 0xe8, 0xc9, - 0x22, 0xd0, 0xf1, 0xb1, 0x19, 0xc9, 0x22, 0xf0, - - 0xea, 0xca, 0x86, 0x36, 0x84, 0x1b, 0xa9, 0x00, - 0x60, 0x4c, 0x98, 0x8e, 0xa4, 0x1b, 0xe6, 0x1b, - - 0xb1, 0x19, 0xc9, 0x20, 0xf0, 0xf6, 0xc9, 0x2d, - 0xf0, 0x92, 0xc9, 0x22, 0xf0, 0xcb, 0xc9, 0x2b, - - 0xd0, 0x03, 0x20, 0x8c, 0x8a, 0xc9, 0x8e, 0x90, - 0x07, 0xc9, 0xc6, 0xb0, 0x36, 0x4c, 0xb1, 0x8b, - - 0xc9, 0x3f, 0xb0, 0x0c, 0xc9, 0x2e, 0xb0, 0x12, - 0xc9, 0x26, 0xf0, 0x51, 0xc9, 0x28, 0xf0, 0x36, - - 0xc6, 0x1b, 0x20, 0xdd, 0x95, 0xf0, 0x09, 0x4c, - 0x2c, 0xb3, 0x20, 0x7b, 0xa0, 0x90, 0x14, 0x60, - - 0xa5, 0x28, 0x29, 0x02, 0xd0, 0x0d, 0xb0, 0x0b, - 0x86, 0x1b, 0xad, 0x40, 0x04, 0xac, 0x41, 0x04, - - 0x4c, 0xea, 0xae, 0x00, 0x1a, 0x4e, 0x6f, 0x20, - 0x73, 0x75, 0x63, 0x68, 0x20, 0x76, 0x61, 0x72, - - 0x69, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x20, 0x29, - 0x9b, 0xe6, 0x1b, 0xe0, 0x29, 0xd0, 0x02, 0xa8, - - 0x60, 0x00, 0x1b, 0x4d, 0x69, 0x73, 0x73, 0x69, - 0x6e, 0x67, 0x20, 0x29, 0x00, 0xa2, 0x00, 0x86, - - 0x2a, 0x86, 0x2b, 0x86, 0x2c, 0x86, 0x2d, 0xa4, - 0x1b, 0xb1, 0x19, 0xc9, 0x30, 0x90, 0x23, 0xc9, - - 0x3a, 0x90, 0x0a, 0xe9, 0x37, 0xc9, 0x0a, 0x90, - 0x19, 0xc9, 0x10, 0xb0, 0x15, 0x0a, 0x0a, 0x0a, - - 0x0a, 0xa2, 0x03, 0x0a, 0x26, 0x2a, 0x26, 0x2b, - 0x26, 0x2c, 0x26, 0x2d, 0xca, 0x10, 0xf4, 0xc8, - - 0xd0, 0xd7, 0x8a, 0x10, 0x05, 0x84, 0x1b, 0xa9, - 0x40, 0x60, 0x00, 0x1c, 0x42, 0x61, 0x64, 0x20, - - 0x48, 0x45, 0x58, 0x00, 0xa2, 0x2a, 0xa0, 0x00, - 0xa9, 0x01, 0x20, 0xf1, 0xff, 0xa9, 0x40, 0x60, - - 0xa9, 0x00, 0xa4, 0x18, 0x4c, 0xea, 0xae, 0x4c, - 0x43, 0xae, 0xa9, 0x00, 0xf0, 0x0a, 0x4c, 0x0e, - - 0x8c, 0x20, 0xec, 0xad, 0xd0, 0xf8, 0xa5, 0x36, - 0xa0, 0x00, 0xf0, 0x0e, 0xa4, 0x1b, 0xb1, 0x19, - - 0xc9, 0x50, 0xd0, 0xe3, 0xe6, 0x1b, 0xa5, 0x12, - 0xa4, 0x13, 0x85, 0x2a, 0x84, 0x2b, 0xa9, 0x00, - - 0x85, 0x2c, 0x85, 0x2d, 0xa9, 0x40, 0x60, 0xa5, - 0x1e, 0x4c, 0xd8, 0xae, 0xa5, 0x00, 0xa4, 0x01, - - 0x4c, 0xea, 0xae, 0xa5, 0x06, 0xa4, 0x07, 0x4c, - 0xea, 0xae, 0xe6, 0x1b, 0x20, 0x56, 0xae, 0x20, - - 0xf0, 0x92, 0xa5, 0x2d, 0x30, 0x29, 0x05, 0x2c, - 0x05, 0x2b, 0xd0, 0x08, 0xa5, 0x2a, 0xf0, 0x4c, - - 0xc9, 0x01, 0xf0, 0x45, 0x20, 0xbe, 0xa2, 0x20, - 0x51, 0xbd, 0x20, 0x69, 0xaf, 0x20, 0x7e, 0xbd, - - 0x20, 0x06, 0xa6, 0x20, 0x03, 0xa3, 0x20, 0xe4, - 0xa3, 0x20, 0x22, 0x92, 0xa9, 0x40, 0x60, 0xa2, - - 0x0d, 0x20, 0x44, 0xbe, 0xa9, 0x40, 0x85, 0x11, - 0x60, 0xa4, 0x1b, 0xb1, 0x19, 0xc9, 0x28, 0xf0, - - 0xb9, 0x20, 0x87, 0xaf, 0xa2, 0x0d, 0xb5, 0x00, - 0x85, 0x2a, 0xb5, 0x01, 0x85, 0x2b, 0xb5, 0x02, - - 0x85, 0x2c, 0xb5, 0x03, 0x85, 0x2d, 0xa9, 0x40, - 0x60, 0x20, 0x87, 0xaf, 0xa2, 0x00, 0x86, 0x2e, - - 0x86, 0x2f, 0x86, 0x35, 0xa9, 0x80, 0x85, 0x30, - 0xb5, 0x0d, 0x95, 0x31, 0xe8, 0xe0, 0x04, 0xd0, - - 0xf7, 0x20, 0x59, 0xa6, 0xa9, 0xff, 0x60, 0xa0, - 0x20, 0xa5, 0x0f, 0x4a, 0x4a, 0x4a, 0x45, 0x11, - - 0x6a, 0x26, 0x0d, 0x26, 0x0e, 0x26, 0x0f, 0x26, - 0x10, 0x26, 0x11, 0x88, 0xd0, 0xeb, 0x60, 0xa4, - - 0x09, 0xa5, 0x08, 0x4c, 0xea, 0xae, 0xa0, 0x00, - 0xb1, 0xfd, 0x4c, 0xea, 0xae, 0x20, 0xe3, 0x92, - - 0xa9, 0x81, 0xa6, 0x2a, 0xa4, 0x2b, 0x4c, 0xf4, - 0xff, 0x20, 0xe0, 0xff, 0x4c, 0xd8, 0xae, 0x20, - - 0xe0, 0xff, 0x8d, 0x00, 0x06, 0xa9, 0x01, 0x85, - 0x36, 0xa9, 0x00, 0x60, 0x20, 0x29, 0x9b, 0xd0, - - 0x62, 0xe0, 0x2c, 0xd0, 0x61, 0xe6, 0x1b, 0x20, - 0xb2, 0xbd, 0x20, 0x56, 0xae, 0x20, 0xf0, 0x92, - - 0x20, 0xcb, 0xbd, 0xa5, 0x2a, 0xc5, 0x36, 0xb0, - 0x02, 0x85, 0x36, 0xa9, 0x00, 0x60, 0x20, 0x29, - - 0x9b, 0xd0, 0x40, 0xe0, 0x2c, 0xd0, 0x3f, 0xe6, - 0x1b, 0x20, 0xb2, 0xbd, 0x20, 0x56, 0xae, 0x20, - - 0xf0, 0x92, 0x20, 0xcb, 0xbd, 0xa5, 0x36, 0x38, - 0xe5, 0x2a, 0x90, 0x17, 0xf0, 0x17, 0xaa, 0xa5, - - 0x2a, 0x85, 0x36, 0xf0, 0x10, 0xa0, 0x00, 0xbd, - 0x00, 0x06, 0x99, 0x00, 0x06, 0xe8, 0xc8, 0xc6, - - 0x2a, 0xd0, 0xf4, 0xa9, 0x00, 0x60, 0x20, 0xad, - 0xaf, 0x8a, 0xc0, 0x00, 0xf0, 0x94, 0xa9, 0x00, - - 0x85, 0x36, 0x60, 0x4c, 0x0e, 0x8c, 0x4c, 0xa2, - 0x8a, 0x20, 0x29, 0x9b, 0xd0, 0xf5, 0xe0, 0x2c, - - 0xd0, 0xf4, 0x20, 0xb2, 0xbd, 0xe6, 0x1b, 0x20, - 0xdd, 0x92, 0xa5, 0x2a, 0x48, 0xa9, 0xff, 0x85, - - 0x2a, 0xe6, 0x1b, 0xe0, 0x29, 0xf0, 0x0a, 0xe0, - 0x2c, 0xd0, 0xdb, 0x20, 0x56, 0xae, 0x20, 0xf0, - - 0x92, 0x20, 0xcb, 0xbd, 0x68, 0xa8, 0x18, 0xf0, - 0x06, 0xe5, 0x36, 0xb0, 0xc1, 0x88, 0x98, 0x85, - - 0x2c, 0xaa, 0xa0, 0x00, 0xa5, 0x36, 0x38, 0xe5, - 0x2c, 0xc5, 0x2a, 0xb0, 0x02, 0x85, 0x2a, 0xa5, - - 0x2a, 0xf0, 0xab, 0xbd, 0x00, 0x06, 0x99, 0x00, - 0x06, 0xc8, 0xe8, 0xc4, 0x2a, 0xd0, 0xf4, 0x84, - - 0x36, 0xa9, 0x00, 0x60, 0x20, 0x8c, 0x8a, 0xa0, - 0xff, 0xc9, 0x7e, 0xf0, 0x04, 0xa0, 0x00, 0xc6, - - 0x1b, 0x98, 0x48, 0x20, 0xec, 0xad, 0xf0, 0x17, - 0xa8, 0x68, 0x85, 0x15, 0xad, 0x03, 0x04, 0xd0, - - 0x08, 0x85, 0x37, 0x20, 0xf9, 0x9e, 0xa9, 0x00, - 0x60, 0x20, 0xdf, 0x9e, 0xa9, 0x00, 0x60, 0x4c, - - 0x0e, 0x8c, 0x20, 0xdd, 0x92, 0x20, 0x94, 0xbd, - 0x20, 0xae, 0x8a, 0x20, 0x56, 0xae, 0xd0, 0xef, - - 0x20, 0xea, 0xbd, 0xa4, 0x36, 0xf0, 0x1e, 0xa5, - 0x2a, 0xf0, 0x1d, 0xc6, 0x2a, 0xf0, 0x16, 0xa2, - - 0x00, 0xbd, 0x00, 0x06, 0x99, 0x00, 0x06, 0xe8, - 0xc8, 0xf0, 0x10, 0xe4, 0x36, 0x90, 0xf2, 0xc6, - - 0x2a, 0xd0, 0xec, 0x84, 0x36, 0xa9, 0x00, 0x60, - 0x85, 0x36, 0x60, 0x4c, 0x03, 0x9c, 0x68, 0x85, - - 0x0c, 0x68, 0x85, 0x0b, 0x00, 0x1d, 0x4e, 0x6f, - 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, 0xa4, 0x2f, - - 0xf2, 0x00, 0xa5, 0x18, 0x85, 0x0c, 0xa9, 0x00, - 0x85, 0x0b, 0xa0, 0x01, 0xb1, 0x0b, 0x30, 0xde, - - 0xa0, 0x03, 0xc8, 0xb1, 0x0b, 0xc9, 0x20, 0xf0, - 0xf9, 0xc9, 0xdd, 0xf0, 0x0f, 0xa0, 0x03, 0xb1, - - 0x0b, 0x18, 0x65, 0x0b, 0x85, 0x0b, 0x90, 0xe2, - 0xe6, 0x0c, 0xb0, 0xde, 0xc8, 0x84, 0x0a, 0x20, - - 0x97, 0x8a, 0x98, 0xaa, 0x18, 0x65, 0x0b, 0xa4, - 0x0c, 0x90, 0x02, 0xc8, 0x18, 0xe9, 0x00, 0x85, - - 0x3c, 0x98, 0xe9, 0x00, 0x85, 0x3d, 0xa0, 0x00, - 0xc8, 0xe8, 0xb1, 0x3c, 0xd1, 0x37, 0xd0, 0xcd, - - 0xc4, 0x39, 0xd0, 0xf4, 0xc8, 0xb1, 0x3c, 0x20, - 0x26, 0x89, 0xb0, 0xc1, 0x8a, 0xa8, 0x20, 0x6d, - - 0x98, 0x20, 0xed, 0x94, 0xa2, 0x01, 0x20, 0x31, - 0x95, 0xa0, 0x00, 0xa5, 0x0b, 0x91, 0x02, 0xc8, - - 0xa5, 0x0c, 0x91, 0x02, 0x20, 0x39, 0x95, 0x4c, - 0xf4, 0xb1, 0x00, 0x1e, 0x42, 0x61, 0x64, 0x20, - - 0x63, 0x61, 0x6c, 0x6c, 0x00, 0xa9, 0xa4, 0x85, - 0x27, 0xba, 0x8a, 0x18, 0x65, 0x04, 0x20, 0x2e, - - 0xbe, 0xa0, 0x00, 0x8a, 0x91, 0x04, 0xe8, 0xc8, - 0xbd, 0x00, 0x01, 0x91, 0x04, 0xe0, 0xff, 0xd0, - - 0xf5, 0x9a, 0xa5, 0x27, 0x48, 0xa5, 0x0a, 0x48, - 0xa5, 0x0b, 0x48, 0xa5, 0x0c, 0x48, 0xa5, 0x1b, - - 0xaa, 0x18, 0x65, 0x19, 0xa4, 0x1a, 0x90, 0x02, - 0xc8, 0x18, 0xe9, 0x01, 0x85, 0x37, 0x98, 0xe9, - - 0x00, 0x85, 0x38, 0xa0, 0x02, 0x20, 0x5b, 0x95, - 0xc0, 0x02, 0xf0, 0xae, 0x86, 0x1b, 0x88, 0x84, - - 0x39, 0x20, 0x5b, 0x94, 0xd0, 0x03, 0x4c, 0x12, - 0xb1, 0xa0, 0x00, 0xb1, 0x2a, 0x85, 0x0b, 0xc8, - - 0xb1, 0x2a, 0x85, 0x0c, 0xa9, 0x00, 0x48, 0x85, - 0x0a, 0x20, 0x97, 0x8a, 0xc9, 0x28, 0xf0, 0x4d, - - 0xc6, 0x0a, 0xa5, 0x1b, 0x48, 0xa5, 0x19, 0x48, - 0xa5, 0x1a, 0x48, 0x20, 0xa3, 0x8b, 0x68, 0x85, - - 0x1a, 0x68, 0x85, 0x19, 0x68, 0x85, 0x1b, 0x68, - 0xf0, 0x0c, 0x85, 0x3f, 0x20, 0x0b, 0xbe, 0x20, - - 0xc1, 0x8c, 0xc6, 0x3f, 0xd0, 0xf6, 0x68, 0x85, - 0x0c, 0x68, 0x85, 0x0b, 0x68, 0x85, 0x0a, 0x68, - - 0xa0, 0x00, 0xb1, 0x04, 0xaa, 0x9a, 0xc8, 0xe8, - 0xb1, 0x04, 0x9d, 0x00, 0x01, 0xe0, 0xff, 0xd0, - - 0xf5, 0x98, 0x65, 0x04, 0x85, 0x04, 0x90, 0x02, - 0xe6, 0x05, 0xa5, 0x27, 0x60, 0xa5, 0x1b, 0x48, - - 0xa5, 0x19, 0x48, 0xa5, 0x1a, 0x48, 0x20, 0x82, - 0x95, 0xf0, 0x5a, 0xa5, 0x1b, 0x85, 0x0a, 0x68, - - 0x85, 0x1a, 0x68, 0x85, 0x19, 0x68, 0x85, 0x1b, - 0x68, 0xaa, 0xa5, 0x2c, 0x48, 0xa5, 0x2b, 0x48, - - 0xa5, 0x2a, 0x48, 0xe8, 0x8a, 0x48, 0x20, 0x0d, - 0xb3, 0x20, 0x97, 0x8a, 0xc9, 0x2c, 0xf0, 0xcd, - - 0xc9, 0x29, 0xd0, 0x31, 0xa9, 0x00, 0x48, 0x20, - 0x8c, 0x8a, 0xc9, 0x28, 0xd0, 0x27, 0x20, 0x29, - - 0x9b, 0x20, 0x90, 0xbd, 0xa5, 0x27, 0x85, 0x2d, - 0x20, 0x94, 0xbd, 0x68, 0xaa, 0xe8, 0x8a, 0x48, - - 0x20, 0x8c, 0x8a, 0xc9, 0x2c, 0xf0, 0xe7, 0xc9, - 0x29, 0xd0, 0x0a, 0x68, 0x68, 0x85, 0x4d, 0x85, - - 0x4e, 0xe4, 0x4d, 0xf0, 0x15, 0xa2, 0xfb, 0x9a, - 0x68, 0x85, 0x0c, 0x68, 0x85, 0x0b, 0x00, 0x1f, - - 0x41, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, - 0x73, 0x00, 0x20, 0xea, 0xbd, 0x68, 0x85, 0x2a, - - 0x68, 0x85, 0x2b, 0x68, 0x85, 0x2c, 0x30, 0x21, - 0xa5, 0x2d, 0xf0, 0xd9, 0x85, 0x27, 0xa2, 0x37, - - 0x20, 0x44, 0xbe, 0xa5, 0x27, 0x10, 0x09, 0x20, - 0x7e, 0xbd, 0x20, 0xb5, 0xa3, 0x4c, 0xf3, 0xb2, - - 0x20, 0xea, 0xbd, 0x20, 0xb7, 0xb4, 0x4c, 0x03, - 0xb3, 0xa5, 0x2d, 0xd0, 0xb8, 0x20, 0xcb, 0xbd, - - 0x20, 0x21, 0x8c, 0xc6, 0x4d, 0xd0, 0xc3, 0xa5, - 0x4e, 0x48, 0x4c, 0x02, 0xb2, 0xa4, 0x2c, 0xc0, - - 0x04, 0xd0, 0x05, 0xa2, 0x37, 0x20, 0x44, 0xbe, - 0x20, 0x2c, 0xb3, 0x08, 0x20, 0x90, 0xbd, 0x28, - - 0xf0, 0x07, 0x30, 0x05, 0xa2, 0x37, 0x20, 0x56, - 0xaf, 0x4c, 0x94, 0xbd, 0xa4, 0x2c, 0x30, 0x54, - - 0xf0, 0x1d, 0xc0, 0x05, 0xf0, 0x1e, 0xa0, 0x03, - 0xb1, 0x2a, 0x85, 0x2d, 0x88, 0xb1, 0x2a, 0x85, - - 0x2c, 0x88, 0xb1, 0x2a, 0xaa, 0x88, 0xb1, 0x2a, - 0x85, 0x2a, 0x86, 0x2b, 0xa9, 0x40, 0x60, 0xb1, - - 0x2a, 0x4c, 0xea, 0xae, 0x88, 0xb1, 0x2a, 0x85, - 0x34, 0x88, 0xb1, 0x2a, 0x85, 0x33, 0x88, 0xb1, - - 0x2a, 0x85, 0x32, 0x88, 0xb1, 0x2a, 0x85, 0x2e, - 0x88, 0xb1, 0x2a, 0x85, 0x30, 0x84, 0x35, 0x84, - - 0x2f, 0x05, 0x2e, 0x05, 0x32, 0x05, 0x33, 0x05, - 0x34, 0xf0, 0x04, 0xa5, 0x2e, 0x09, 0x80, 0x85, - - 0x31, 0xa9, 0xff, 0x60, 0xc0, 0x80, 0xf0, 0x1f, - 0xa0, 0x03, 0xb1, 0x2a, 0x85, 0x36, 0xf0, 0x16, - - 0xa0, 0x01, 0xb1, 0x2a, 0x85, 0x38, 0x88, 0xb1, - 0x2a, 0x85, 0x37, 0xa4, 0x36, 0x88, 0xb1, 0x37, - - 0x99, 0x00, 0x06, 0x98, 0xd0, 0xf7, 0x60, 0xa5, - 0x2b, 0xf0, 0x15, 0xa0, 0x00, 0xb1, 0x2a, 0x99, - - 0x00, 0x06, 0x49, 0x0d, 0xf0, 0x04, 0xc8, 0xd0, - 0xf4, 0x98, 0x84, 0x36, 0x60, 0x20, 0xe3, 0x92, - - 0xa5, 0x2a, 0x4c, 0xc2, 0xaf, 0xa0, 0x00, 0x84, - 0x08, 0x84, 0x09, 0xa6, 0x18, 0x86, 0x38, 0x84, - - 0x37, 0xa6, 0x0c, 0xe0, 0x07, 0xf0, 0x2a, 0xa6, - 0x0b, 0x20, 0x42, 0x89, 0xc9, 0x0d, 0xd0, 0x19, - - 0xe4, 0x37, 0xa5, 0x0c, 0xe5, 0x38, 0x90, 0x19, - 0x20, 0x42, 0x89, 0x09, 0x00, 0x30, 0x12, 0x85, - - 0x09, 0x20, 0x42, 0x89, 0x85, 0x08, 0x20, 0x42, - 0x89, 0xe4, 0x37, 0xa5, 0x0c, 0xe5, 0x38, 0xb0, - - 0xd8, 0x60, 0x20, 0xc5, 0xb3, 0x84, 0x20, 0xb1, - 0xfd, 0xd0, 0x08, 0xa9, 0x33, 0x85, 0x16, 0xa9, - - 0xb4, 0x85, 0x17, 0xa5, 0x16, 0x85, 0x0b, 0xa5, - 0x17, 0x85, 0x0c, 0x20, 0x3a, 0xbd, 0xaa, 0x86, - - 0x0a, 0xa9, 0xda, 0x20, 0xf4, 0xff, 0xa9, 0x7e, - 0x20, 0xf4, 0xff, 0xa2, 0xff, 0x86, 0x28, 0x9a, - - 0x4c, 0xa3, 0x8b, 0xf6, 0x3a, 0xe7, 0x9e, 0xf1, - 0x22, 0x20, 0x61, 0x74, 0x20, 0x6c, 0x69, 0x6e, - - 0x65, 0x20, 0x22, 0x3b, 0x9e, 0x3a, 0xe0, 0x8b, - 0xf1, 0x3a, 0xe0, 0x0d, 0x20, 0x21, 0x88, 0xa2, - - 0x03, 0xa5, 0x2a, 0x48, 0xa5, 0x2b, 0x48, 0x8a, - 0x48, 0x20, 0xda, 0x92, 0x68, 0xaa, 0xca, 0xd0, - - 0xf0, 0x20, 0x52, 0x98, 0xa5, 0x2a, 0x85, 0x3d, - 0xa5, 0x2b, 0x85, 0x3e, 0xa0, 0x07, 0xa2, 0x05, - - 0xd0, 0x1d, 0x20, 0x21, 0x88, 0xa2, 0x0d, 0xa5, - 0x2a, 0x48, 0x8a, 0x48, 0x20, 0xda, 0x92, 0x68, - - 0xaa, 0xca, 0xd0, 0xf3, 0x20, 0x52, 0x98, 0xa5, - 0x2a, 0x85, 0x44, 0xa2, 0x0c, 0xa0, 0x08, 0x68, - - 0x95, 0x37, 0xca, 0x10, 0xfa, 0x98, 0xa2, 0x37, - 0xa0, 0x00, 0x20, 0xf1, 0xff, 0x4c, 0x9b, 0x8b, - - 0x20, 0x21, 0x88, 0x20, 0x52, 0x98, 0xa4, 0x2a, - 0x88, 0x84, 0x23, 0x4c, 0x9b, 0x8b, 0x4c, 0x0e, - - 0x8c, 0x20, 0x29, 0x9b, 0x20, 0x0b, 0xbe, 0xa5, - 0x39, 0xc9, 0x05, 0xf0, 0x23, 0xa5, 0x27, 0xf0, - - 0xed, 0x10, 0x03, 0x20, 0xe4, 0xa3, 0xa0, 0x00, - 0xa5, 0x2a, 0x91, 0x37, 0xa5, 0x39, 0xf0, 0x0f, - - 0xa5, 0x2b, 0xc8, 0x91, 0x37, 0xa5, 0x2c, 0xc8, - 0x91, 0x37, 0xa5, 0x2d, 0xc8, 0x91, 0x37, 0x60, - - 0xa5, 0x27, 0xf0, 0xca, 0x30, 0x03, 0x20, 0xbe, - 0xa2, 0xa0, 0x00, 0xa5, 0x30, 0x91, 0x37, 0xc8, - - 0xa5, 0x2e, 0x29, 0x80, 0x85, 0x2e, 0xa5, 0x31, - 0x29, 0x7f, 0x05, 0x2e, 0x91, 0x37, 0xc8, 0xa5, - - 0x32, 0x91, 0x37, 0xc8, 0xa5, 0x33, 0x91, 0x37, - 0xc8, 0xa5, 0x34, 0x91, 0x37, 0x60, 0x85, 0x37, - - 0xc9, 0x80, 0x90, 0x44, 0xa9, 0x71, 0x85, 0x38, - 0xa9, 0x80, 0x85, 0x39, 0x84, 0x3a, 0xa0, 0x00, - - 0xc8, 0xb1, 0x38, 0x10, 0xfb, 0xc5, 0x37, 0xf0, - 0x0d, 0xc8, 0x98, 0x38, 0x65, 0x38, 0x85, 0x38, - - 0x90, 0xec, 0xe6, 0x39, 0xb0, 0xe8, 0xa0, 0x00, - 0xb1, 0x38, 0x30, 0x06, 0x20, 0x58, 0xb5, 0xc8, - - 0xd0, 0xf6, 0xa4, 0x3a, 0x60, 0x48, 0x4a, 0x4a, - 0x4a, 0x4a, 0x20, 0x50, 0xb5, 0x68, 0x29, 0x0f, - - 0xc9, 0x0a, 0x90, 0x02, 0x69, 0x06, 0x69, 0x30, - 0xc9, 0x0d, 0xd0, 0x0b, 0x20, 0xee, 0xff, 0x4c, - - 0x28, 0xbc, 0x20, 0x45, 0xb5, 0xa9, 0x20, 0x48, - 0xa5, 0x23, 0xc5, 0x1e, 0xb0, 0x03, 0x20, 0x25, - - 0xbc, 0x68, 0xe6, 0x1e, 0x6c, 0x0e, 0x02, 0x25, - 0x1f, 0xf0, 0x0e, 0x8a, 0xf0, 0x0b, 0x30, 0xe5, - - 0x20, 0x65, 0xb5, 0x20, 0x58, 0xb5, 0xca, 0xd0, - 0xf7, 0x60, 0xe6, 0x0a, 0x20, 0x1d, 0x9b, 0x20, - - 0x4c, 0x98, 0x20, 0xee, 0x92, 0xa5, 0x2a, 0x85, - 0x1f, 0x4c, 0xf6, 0x8a, 0xc8, 0xb1, 0x0b, 0xc9, - - 0x4f, 0xf0, 0xe7, 0xa9, 0x00, 0x85, 0x3b, 0x85, - 0x3c, 0x20, 0xd8, 0xae, 0x20, 0xdf, 0x97, 0x08, - - 0x20, 0x94, 0xbd, 0xa9, 0xff, 0x85, 0x2a, 0xa9, - 0x7f, 0x85, 0x2b, 0x28, 0x90, 0x11, 0x20, 0x97, - - 0x8a, 0xc9, 0x2c, 0xf0, 0x13, 0x20, 0xea, 0xbd, - 0x20, 0x94, 0xbd, 0xc6, 0x0a, 0x10, 0x0c, 0x20, - - 0x97, 0x8a, 0xc9, 0x2c, 0xf0, 0x02, 0xc6, 0x0a, - 0x20, 0xdf, 0x97, 0xa5, 0x2a, 0x85, 0x31, 0xa5, - - 0x2b, 0x85, 0x32, 0x20, 0x57, 0x98, 0x20, 0x6f, - 0xbe, 0x20, 0xea, 0xbd, 0x20, 0x70, 0x99, 0xa5, - - 0x3d, 0x85, 0x0b, 0xa5, 0x3e, 0x85, 0x0c, 0x90, - 0x16, 0x88, 0xb0, 0x06, 0x20, 0x25, 0xbc, 0x20, - - 0x6d, 0x98, 0xb1, 0x0b, 0x85, 0x2b, 0xc8, 0xb1, - 0x0b, 0x85, 0x2a, 0xc8, 0xc8, 0x84, 0x0a, 0xa5, - - 0x2a, 0x18, 0xe5, 0x31, 0xa5, 0x2b, 0xe5, 0x32, - 0x90, 0x03, 0x4c, 0xf6, 0x8a, 0x20, 0x23, 0x99, - - 0xa2, 0xff, 0x86, 0x4d, 0xa9, 0x01, 0x20, 0x77, - 0xb5, 0xa6, 0x3b, 0xa9, 0x02, 0x20, 0x77, 0xb5, - - 0xa6, 0x3c, 0xa9, 0x04, 0x20, 0x77, 0xb5, 0xa4, - 0x0a, 0xb1, 0x0b, 0xc9, 0x0d, 0xf0, 0xbd, 0xc9, - - 0x22, 0xd0, 0x0e, 0xa9, 0xff, 0x45, 0x4d, 0x85, - 0x4d, 0xa9, 0x22, 0x20, 0x58, 0xb5, 0xc8, 0xd0, - - 0xe8, 0x24, 0x4d, 0x10, 0xf6, 0xc9, 0x8d, 0xd0, - 0x0f, 0x20, 0xeb, 0x97, 0x84, 0x0a, 0xa9, 0x00, - - 0x85, 0x14, 0x20, 0x1f, 0x99, 0x4c, 0x37, 0xb6, - 0xc9, 0xe3, 0xd0, 0x02, 0xe6, 0x3b, 0xc9, 0xed, - - 0xd0, 0x06, 0xa6, 0x3b, 0xf0, 0x02, 0xc6, 0x3b, - 0xc9, 0xf5, 0xd0, 0x02, 0xe6, 0x3c, 0xc9, 0xfd, - - 0xd0, 0x06, 0xa6, 0x3c, 0xf0, 0x02, 0xc6, 0x3c, - 0x20, 0x0e, 0xb5, 0xc8, 0xd0, 0xab, 0x00, 0x20, - - 0x4e, 0x6f, 0x20, 0xe3, 0x00, 0x20, 0xc9, 0x95, - 0xd0, 0x09, 0xa6, 0x26, 0xf0, 0xf0, 0xb0, 0x37, - - 0x4c, 0x2a, 0x98, 0xb0, 0xfb, 0xa6, 0x26, 0xf0, - 0xe5, 0xa5, 0x2a, 0xdd, 0xf1, 0x04, 0xd0, 0x0e, - - 0xa5, 0x2b, 0xdd, 0xf2, 0x04, 0xd0, 0x07, 0xa5, - 0x2c, 0xdd, 0xf3, 0x04, 0xf0, 0x19, 0x8a, 0x38, - - 0xe9, 0x0f, 0xaa, 0x86, 0x26, 0xd0, 0xe2, 0x00, - 0x21, 0x43, 0x61, 0x6e, 0x27, 0x74, 0x20, 0x4d, - - 0x61, 0x74, 0x63, 0x68, 0x20, 0xe3, 0x00, 0xbd, - 0xf1, 0x04, 0x85, 0x2a, 0xbd, 0xf2, 0x04, 0x85, - - 0x2b, 0xbc, 0xf3, 0x04, 0xc0, 0x05, 0xf0, 0x7e, - 0xa0, 0x00, 0xb1, 0x2a, 0x7d, 0xf4, 0x04, 0x91, - - 0x2a, 0x85, 0x37, 0xc8, 0xb1, 0x2a, 0x7d, 0xf5, - 0x04, 0x91, 0x2a, 0x85, 0x38, 0xc8, 0xb1, 0x2a, - - 0x7d, 0xf6, 0x04, 0x91, 0x2a, 0x85, 0x39, 0xc8, - 0xb1, 0x2a, 0x7d, 0xf7, 0x04, 0x91, 0x2a, 0xa8, - - 0xa5, 0x37, 0x38, 0xfd, 0xf9, 0x04, 0x85, 0x37, - 0xa5, 0x38, 0xfd, 0xfa, 0x04, 0x85, 0x38, 0xa5, - - 0x39, 0xfd, 0xfb, 0x04, 0x85, 0x39, 0x98, 0xfd, - 0xfc, 0x04, 0x05, 0x37, 0x05, 0x38, 0x05, 0x39, - - 0xf0, 0x0f, 0x98, 0x5d, 0xf7, 0x04, 0x5d, 0xfc, - 0x04, 0x10, 0x04, 0xb0, 0x04, 0x90, 0x12, 0xb0, - - 0x10, 0xbc, 0xfe, 0x04, 0xbd, 0xff, 0x04, 0x84, - 0x0b, 0x85, 0x0c, 0x20, 0x77, 0x98, 0x4c, 0xa3, - - 0x8b, 0xa5, 0x26, 0x38, 0xe9, 0x0f, 0x85, 0x26, - 0xa4, 0x1b, 0x84, 0x0a, 0x20, 0x97, 0x8a, 0xc9, - - 0x2c, 0xd0, 0x3e, 0x4c, 0x95, 0xb6, 0x20, 0x54, - 0xb3, 0xa5, 0x26, 0x18, 0x69, 0xf4, 0x85, 0x4b, - - 0xa9, 0x05, 0x85, 0x4c, 0x20, 0x00, 0xa5, 0xa5, - 0x2a, 0x85, 0x37, 0xa5, 0x2b, 0x85, 0x38, 0x20, - - 0xe9, 0xb4, 0xa5, 0x26, 0x85, 0x27, 0x18, 0x69, - 0xf9, 0x85, 0x4b, 0xa9, 0x05, 0x85, 0x4c, 0x20, - - 0x5f, 0x9a, 0xf0, 0xad, 0xbd, 0xf5, 0x04, 0x30, - 0x04, 0xb0, 0xa6, 0x90, 0xb4, 0x90, 0xa2, 0xb0, - - 0xb0, 0x4c, 0x96, 0x8b, 0x00, 0x22, 0xe3, 0x20, - 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, - - 0x00, 0x23, 0x54, 0x6f, 0x6f, 0x20, 0x6d, 0x61, - 0x6e, 0x79, 0x20, 0xe3, 0x73, 0x00, 0x24, 0x4e, - - 0x6f, 0x20, 0xb8, 0x00, 0x20, 0x82, 0x95, 0xf0, - 0xdb, 0xb0, 0xd9, 0x20, 0x94, 0xbd, 0x20, 0x41, - - 0x98, 0x20, 0xb1, 0xb4, 0xa4, 0x26, 0xc0, 0x96, - 0xb0, 0xd6, 0xa5, 0x37, 0x99, 0x00, 0x05, 0xa5, - - 0x38, 0x99, 0x01, 0x05, 0xa5, 0x39, 0x99, 0x02, - 0x05, 0xaa, 0x20, 0x8c, 0x8a, 0xc9, 0xb8, 0xd0, - - 0xcc, 0xe0, 0x05, 0xf0, 0x5a, 0x20, 0xdd, 0x92, - 0xa4, 0x26, 0xa5, 0x2a, 0x99, 0x08, 0x05, 0xa5, - - 0x2b, 0x99, 0x09, 0x05, 0xa5, 0x2c, 0x99, 0x0a, - 0x05, 0xa5, 0x2d, 0x99, 0x0b, 0x05, 0xa9, 0x01, - - 0x20, 0xd8, 0xae, 0x20, 0x8c, 0x8a, 0xc9, 0x88, - 0xd0, 0x05, 0x20, 0xdd, 0x92, 0xa4, 0x1b, 0x84, - - 0x0a, 0xa4, 0x26, 0xa5, 0x2a, 0x99, 0x03, 0x05, - 0xa5, 0x2b, 0x99, 0x04, 0x05, 0xa5, 0x2c, 0x99, - - 0x05, 0x05, 0xa5, 0x2d, 0x99, 0x06, 0x05, 0x20, - 0x80, 0x98, 0xa4, 0x26, 0xa5, 0x0b, 0x99, 0x0d, - - 0x05, 0xa5, 0x0c, 0x99, 0x0e, 0x05, 0x18, 0x98, - 0x69, 0x0f, 0x85, 0x26, 0x4c, 0xa3, 0x8b, 0x20, - - 0x29, 0x9b, 0x20, 0xfd, 0x92, 0xa5, 0x26, 0x18, - 0x69, 0x08, 0x85, 0x4b, 0xa9, 0x05, 0x85, 0x4c, - - 0x20, 0x8d, 0xa3, 0x20, 0x99, 0xa6, 0x20, 0x8c, - 0x8a, 0xc9, 0x88, 0xd0, 0x08, 0x20, 0x29, 0x9b, - - 0x20, 0xfd, 0x92, 0xa4, 0x1b, 0x84, 0x0a, 0xa5, - 0x26, 0x18, 0x69, 0x03, 0x85, 0x4b, 0xa9, 0x05, - - 0x85, 0x4c, 0x20, 0x8d, 0xa3, 0x4c, 0x37, 0xb8, - 0x20, 0x9a, 0xb9, 0x20, 0x57, 0x98, 0xa4, 0x25, - - 0xc0, 0x1a, 0xb0, 0x0e, 0xa5, 0x0b, 0x99, 0xcc, - 0x05, 0xa5, 0x0c, 0x99, 0xe6, 0x05, 0xe6, 0x25, - - 0x90, 0x30, 0x00, 0x25, 0x54, 0x6f, 0x6f, 0x20, - 0x6d, 0x61, 0x6e, 0x79, 0x20, 0xe4, 0x73, 0x00, - - 0x26, 0x4e, 0x6f, 0x20, 0xe4, 0x00, 0x20, 0x57, - 0x98, 0xa6, 0x25, 0xf0, 0xf2, 0xc6, 0x25, 0xbc, - - 0xcb, 0x05, 0xbd, 0xe5, 0x05, 0x84, 0x0b, 0x85, - 0x0c, 0x4c, 0x9b, 0x8b, 0x20, 0x9a, 0xb9, 0x20, - - 0x57, 0x98, 0xa5, 0x20, 0xf0, 0x03, 0x20, 0x05, - 0x99, 0xa4, 0x3d, 0xa5, 0x3e, 0x84, 0x0b, 0x85, - - 0x0c, 0x4c, 0xa3, 0x8b, 0x20, 0x57, 0x98, 0xa9, - 0x33, 0x85, 0x16, 0xa9, 0xb4, 0x85, 0x17, 0x4c, - - 0x9b, 0x8b, 0x20, 0x97, 0x8a, 0xc9, 0x87, 0xf0, - 0xeb, 0xa4, 0x0a, 0x88, 0x20, 0x6d, 0x98, 0xa5, - - 0x0b, 0x85, 0x16, 0xa5, 0x0c, 0x85, 0x17, 0x4c, - 0x7d, 0x8b, 0x00, 0x27, 0xee, 0x20, 0x73, 0x79, - - 0x6e, 0x74, 0x61, 0x78, 0x00, 0x20, 0x97, 0x8a, - 0xc9, 0x85, 0xf0, 0xd6, 0xc6, 0x0a, 0x20, 0x1d, - - 0x9b, 0x20, 0xf0, 0x92, 0xa4, 0x1b, 0xc8, 0x84, - 0x0a, 0xe0, 0xe5, 0xf0, 0x04, 0xe0, 0xe4, 0xd0, - - 0xd9, 0x8a, 0x48, 0xa5, 0x2b, 0x05, 0x2c, 0x05, - 0x2d, 0xd0, 0x42, 0xa6, 0x2a, 0xf0, 0x3e, 0xca, - - 0xf0, 0x1a, 0xa4, 0x0a, 0xb1, 0x0b, 0xc8, 0xc9, - 0x0d, 0xf0, 0x32, 0xc9, 0x3a, 0xf0, 0x2e, 0xc9, - - 0x8b, 0xf0, 0x2a, 0xc9, 0x2c, 0xd0, 0xed, 0xca, - 0xd0, 0xea, 0x84, 0x0a, 0x20, 0x9a, 0xb9, 0x68, - - 0xc9, 0xe4, 0xf0, 0x06, 0x20, 0x77, 0x98, 0x4c, - 0xd2, 0xb8, 0xa4, 0x0a, 0xb1, 0x0b, 0xc8, 0xc9, - - 0x0d, 0xf0, 0x04, 0xc9, 0x3a, 0xd0, 0xf5, 0x88, - 0x84, 0x0a, 0x4c, 0x8b, 0xb8, 0xa4, 0x0a, 0x68, - - 0xb1, 0x0b, 0xc8, 0xc9, 0x8b, 0xf0, 0x0e, 0xc9, - 0x0d, 0xd0, 0xf5, 0x00, 0x28, 0xee, 0x20, 0x72, - - 0x61, 0x6e, 0x67, 0x65, 0x00, 0x84, 0x0a, 0x4c, - 0xe3, 0x98, 0x20, 0xdf, 0x97, 0xb0, 0x10, 0x20, - - 0x1d, 0x9b, 0x20, 0xf0, 0x92, 0xa5, 0x1b, 0x85, - 0x0a, 0xa5, 0x2b, 0x29, 0x7f, 0x85, 0x2b, 0x20, - - 0x70, 0x99, 0xb0, 0x01, 0x60, 0x00, 0x29, 0x4e, - 0x6f, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, 0x6c, - - 0x69, 0x6e, 0x65, 0x00, 0x4c, 0x0e, 0x8c, 0x4c, - 0x2a, 0x98, 0x84, 0x0a, 0x4c, 0x98, 0x8b, 0xc6, - - 0x0a, 0x20, 0xa9, 0xbf, 0xa5, 0x1b, 0x85, 0x0a, - 0x84, 0x4d, 0x20, 0x97, 0x8a, 0xc9, 0x2c, 0xd0, - - 0xe9, 0xa5, 0x4d, 0x48, 0x20, 0x82, 0x95, 0xf0, - 0xde, 0xa5, 0x1b, 0x85, 0x0a, 0x68, 0x85, 0x4d, - - 0x08, 0x20, 0x94, 0xbd, 0xa4, 0x4d, 0x20, 0xd7, - 0xff, 0x85, 0x27, 0x28, 0x90, 0x1b, 0xa5, 0x27, - - 0xd0, 0xc2, 0x20, 0xd7, 0xff, 0x85, 0x36, 0xaa, - 0xf0, 0x09, 0x20, 0xd7, 0xff, 0x9d, 0xff, 0x05, - - 0xca, 0xd0, 0xf7, 0x20, 0x1e, 0x8c, 0x4c, 0xda, - 0xb9, 0xa5, 0x27, 0xf0, 0xa7, 0x30, 0x0c, 0xa2, - - 0x03, 0x20, 0xd7, 0xff, 0x95, 0x2a, 0xca, 0x10, - 0xf8, 0x30, 0x0e, 0xa2, 0x04, 0x20, 0xd7, 0xff, - - 0x9d, 0x6c, 0x04, 0xca, 0x10, 0xf7, 0x20, 0xb2, - 0xa3, 0x20, 0xb4, 0xb4, 0x4c, 0xda, 0xb9, 0x68, - - 0x68, 0x4c, 0x98, 0x8b, 0x20, 0x97, 0x8a, 0xc9, - 0x23, 0xf0, 0x84, 0xc9, 0x86, 0xf0, 0x03, 0xc6, - - 0x0a, 0x18, 0x66, 0x4d, 0x46, 0x4d, 0xa9, 0xff, - 0x85, 0x4e, 0x20, 0x8a, 0x8e, 0xb0, 0x0a, 0x20, - - 0x8a, 0x8e, 0x90, 0xfb, 0xa2, 0xff, 0x86, 0x4e, - 0x18, 0x08, 0x06, 0x4d, 0x28, 0x66, 0x4d, 0xc9, - - 0x2c, 0xf0, 0xe7, 0xc9, 0x3b, 0xf0, 0xe3, 0xc6, - 0x0a, 0xa5, 0x4d, 0x48, 0xa5, 0x4e, 0x48, 0x20, - - 0x82, 0x95, 0xf0, 0xbb, 0x68, 0x85, 0x4e, 0x68, - 0x85, 0x4d, 0xa5, 0x1b, 0x85, 0x0a, 0x08, 0x24, - - 0x4d, 0x70, 0x06, 0xa5, 0x4e, 0xc9, 0xff, 0xd0, - 0x17, 0x24, 0x4d, 0x10, 0x05, 0xa9, 0x3f, 0x20, - - 0x58, 0xb5, 0x20, 0xfc, 0xbb, 0x84, 0x36, 0x06, - 0x4d, 0x18, 0x66, 0x4d, 0x24, 0x4d, 0x70, 0x1d, - - 0x85, 0x1b, 0xa9, 0x00, 0x85, 0x19, 0xa9, 0x06, - 0x85, 0x1a, 0x20, 0xad, 0xad, 0x20, 0x8c, 0x8a, - - 0xc9, 0x2c, 0xf0, 0x06, 0xc9, 0x0d, 0xd0, 0xf5, - 0xa0, 0xfe, 0xc8, 0x84, 0x4e, 0x28, 0xb0, 0x0c, - - 0x20, 0x94, 0xbd, 0x20, 0x34, 0xac, 0x20, 0xb4, - 0xb4, 0x4c, 0x5a, 0xba, 0xa9, 0x00, 0x85, 0x27, - - 0x20, 0x21, 0x8c, 0x4c, 0x5a, 0xba, 0xa0, 0x00, - 0x84, 0x3d, 0xa4, 0x18, 0x84, 0x3e, 0x20, 0x97, - - 0x8a, 0xc6, 0x0a, 0xc9, 0x3a, 0xf0, 0x10, 0xc9, - 0x0d, 0xf0, 0x0c, 0xc9, 0x8b, 0xf0, 0x08, 0x20, - - 0x9a, 0xb9, 0xa0, 0x01, 0x20, 0x55, 0xbe, 0x20, - 0x57, 0x98, 0xa5, 0x3d, 0x85, 0x1c, 0xa5, 0x3e, - - 0x85, 0x1d, 0x4c, 0x9b, 0x8b, 0x20, 0x97, 0x8a, - 0xc9, 0x2c, 0xf0, 0x03, 0x4c, 0x96, 0x8b, 0x20, - - 0x82, 0x95, 0xf0, 0xf1, 0xb0, 0x0c, 0x20, 0x50, - 0xbb, 0x20, 0x94, 0xbd, 0x20, 0xb1, 0xb4, 0x4c, - - 0x40, 0xbb, 0x20, 0x50, 0xbb, 0x20, 0x94, 0xbd, - 0x20, 0xad, 0xad, 0x85, 0x27, 0x20, 0x1e, 0x8c, - - 0x18, 0xa5, 0x1b, 0x65, 0x19, 0x85, 0x1c, 0xa5, - 0x1a, 0x69, 0x00, 0x85, 0x1d, 0x4c, 0x15, 0xbb, - - 0xa5, 0x1b, 0x85, 0x0a, 0xa5, 0x1c, 0x85, 0x19, - 0xa5, 0x1d, 0x85, 0x1a, 0xa0, 0x00, 0x84, 0x1b, - - 0x20, 0x8c, 0x8a, 0xc9, 0x2c, 0xf0, 0x49, 0xc9, - 0xdc, 0xf0, 0x45, 0xc9, 0x0d, 0xf0, 0x0b, 0x20, - - 0x8c, 0x8a, 0xc9, 0x2c, 0xf0, 0x3a, 0xc9, 0x0d, - 0xd0, 0xf5, 0xa4, 0x1b, 0xb1, 0x19, 0x30, 0x1c, - - 0xc8, 0xc8, 0xb1, 0x19, 0xaa, 0xc8, 0xb1, 0x19, - 0xc9, 0x20, 0xf0, 0xf9, 0xc9, 0xdc, 0xf0, 0x1d, - - 0x8a, 0x18, 0x65, 0x19, 0x85, 0x19, 0x90, 0xe2, - 0xe6, 0x1a, 0xb0, 0xde, 0x00, 0x2a, 0x4f, 0x75, - - 0x74, 0x20, 0x6f, 0x66, 0x20, 0xdc, 0x00, 0x2b, - 0x4e, 0x6f, 0x20, 0xf5, 0x00, 0xc8, 0x84, 0x1b, - - 0x60, 0x20, 0x1d, 0x9b, 0x20, 0x4c, 0x98, 0x20, - 0xee, 0x92, 0xa6, 0x24, 0xf0, 0xe8, 0xa5, 0x2a, - - 0x05, 0x2b, 0x05, 0x2c, 0x05, 0x2d, 0xf0, 0x05, - 0xc6, 0x24, 0x4c, 0x9b, 0x8b, 0xbc, 0xa3, 0x05, - - 0xbd, 0xb7, 0x05, 0x4c, 0xdd, 0xb8, 0x00, 0x2c, - 0x54, 0x6f, 0x6f, 0x20, 0x6d, 0x61, 0x6e, 0x79, - - 0x20, 0xf5, 0x73, 0x00, 0xa6, 0x24, 0xe0, 0x14, - 0xb0, 0xec, 0x20, 0x6d, 0x98, 0xa5, 0x0b, 0x9d, - - 0xa4, 0x05, 0xa5, 0x0c, 0x9d, 0xb8, 0x05, 0xe6, - 0x24, 0x4c, 0xa3, 0x8b, 0xa0, 0x00, 0xa9, 0x06, - - 0xd0, 0x07, 0x20, 0x58, 0xb5, 0xa0, 0x00, 0xa9, - 0x07, 0x84, 0x37, 0x85, 0x38, 0xa9, 0xee, 0x85, - - 0x39, 0xa9, 0x20, 0x85, 0x3a, 0xa0, 0xff, 0x84, - 0x3b, 0xc8, 0xa2, 0x37, 0x98, 0x20, 0xf1, 0xff, - - 0x90, 0x06, 0x4c, 0x38, 0x98, 0x20, 0xe7, 0xff, - 0xa9, 0x00, 0x85, 0x1e, 0x60, 0x20, 0x70, 0x99, - - 0xb0, 0x4e, 0xa5, 0x3d, 0xe9, 0x02, 0x85, 0x37, - 0x85, 0x3d, 0x85, 0x12, 0xa5, 0x3e, 0xe9, 0x00, - - 0x85, 0x38, 0x85, 0x13, 0x85, 0x3e, 0xa0, 0x03, - 0xb1, 0x37, 0x18, 0x65, 0x37, 0x85, 0x37, 0x90, - - 0x02, 0xe6, 0x38, 0xa0, 0x00, 0xb1, 0x37, 0x91, - 0x12, 0xc9, 0x0d, 0xf0, 0x09, 0xc8, 0xd0, 0xf5, - - 0xe6, 0x38, 0xe6, 0x13, 0xd0, 0xef, 0xc8, 0xd0, - 0x04, 0xe6, 0x38, 0xe6, 0x13, 0xb1, 0x37, 0x91, - - 0x12, 0x30, 0x09, 0x20, 0x81, 0xbc, 0x20, 0x81, - 0xbc, 0x4c, 0x5d, 0xbc, 0x20, 0x92, 0xbe, 0x18, - - 0x60, 0xc8, 0xd0, 0x04, 0xe6, 0x13, 0xe6, 0x38, - 0xb1, 0x37, 0x91, 0x12, 0x60, 0x84, 0x3b, 0x20, - - 0x2d, 0xbc, 0xa0, 0x07, 0x84, 0x3c, 0xa0, 0x00, - 0xa9, 0x0d, 0xd1, 0x3b, 0xf0, 0x72, 0xc8, 0xd1, - - 0x3b, 0xd0, 0xfb, 0xc8, 0xc8, 0xc8, 0x84, 0x3f, - 0xe6, 0x3f, 0xa5, 0x12, 0x85, 0x39, 0xa5, 0x13, - - 0x85, 0x3a, 0x20, 0x92, 0xbe, 0x85, 0x37, 0xa5, - 0x13, 0x85, 0x38, 0x88, 0xa5, 0x06, 0xc5, 0x12, - - 0xa5, 0x07, 0xe5, 0x13, 0xb0, 0x10, 0x20, 0x6f, - 0xbe, 0x20, 0x20, 0xbd, 0x00, 0x00, 0x86, 0x20, - - 0x73, 0x70, 0x61, 0x63, 0x65, 0x00, 0xb1, 0x39, - 0x91, 0x37, 0x98, 0xd0, 0x04, 0xc6, 0x3a, 0xc6, - - 0x38, 0x88, 0x98, 0x65, 0x39, 0xa6, 0x3a, 0x90, - 0x01, 0xe8, 0xc5, 0x3d, 0x8a, 0xe5, 0x3e, 0xb0, - - 0xe5, 0x38, 0xa0, 0x01, 0xa5, 0x2b, 0x91, 0x3d, - 0xc8, 0xa5, 0x2a, 0x91, 0x3d, 0xc8, 0xa5, 0x3f, - - 0x91, 0x3d, 0x20, 0x56, 0xbe, 0xa0, 0xff, 0xc8, - 0xb1, 0x3b, 0x91, 0x3d, 0xc9, 0x0d, 0xd0, 0xf7, - - 0x60, 0x20, 0x57, 0x98, 0x20, 0x20, 0xbd, 0xa5, - 0x18, 0x85, 0x0c, 0x86, 0x0b, 0x4c, 0x0b, 0x8b, - - 0xa5, 0x12, 0x85, 0x00, 0x85, 0x02, 0xa5, 0x13, - 0x85, 0x01, 0x85, 0x03, 0x20, 0x3a, 0xbd, 0xa2, - - 0x80, 0xa9, 0x00, 0x9d, 0x7f, 0x04, 0xca, 0xd0, - 0xfa, 0x60, 0xa5, 0x18, 0x85, 0x1d, 0xa5, 0x06, - - 0x85, 0x04, 0xa5, 0x07, 0x85, 0x05, 0xa9, 0x00, - 0x85, 0x24, 0x85, 0x26, 0x85, 0x25, 0x85, 0x1c, - - 0x60, 0xa5, 0x04, 0x38, 0xe9, 0x05, 0x20, 0x2e, - 0xbe, 0xa0, 0x00, 0xa5, 0x30, 0x91, 0x04, 0xc8, - - 0xa5, 0x2e, 0x29, 0x80, 0x85, 0x2e, 0xa5, 0x31, - 0x29, 0x7f, 0x05, 0x2e, 0x91, 0x04, 0xc8, 0xa5, - - 0x32, 0x91, 0x04, 0xc8, 0xa5, 0x33, 0x91, 0x04, - 0xc8, 0xa5, 0x34, 0x91, 0x04, 0x60, 0xa5, 0x04, - - 0x18, 0x85, 0x4b, 0x69, 0x05, 0x85, 0x04, 0xa5, - 0x05, 0x85, 0x4c, 0x69, 0x00, 0x85, 0x05, 0x60, - - 0xf0, 0x20, 0x30, 0xbd, 0xa5, 0x04, 0x38, 0xe9, - 0x04, 0x20, 0x2e, 0xbe, 0xa0, 0x03, 0xa5, 0x2d, - - 0x91, 0x04, 0x88, 0xa5, 0x2c, 0x91, 0x04, 0x88, - 0xa5, 0x2b, 0x91, 0x04, 0x88, 0xa5, 0x2a, 0x91, - - 0x04, 0x60, 0x18, 0xa5, 0x04, 0xe5, 0x36, 0x20, - 0x2e, 0xbe, 0xa4, 0x36, 0xf0, 0x08, 0xb9, 0xff, - - 0x05, 0x91, 0x04, 0x88, 0xd0, 0xf8, 0xa5, 0x36, - 0x91, 0x04, 0x60, 0xa0, 0x00, 0xb1, 0x04, 0x85, - - 0x36, 0xf0, 0x09, 0xa8, 0xb1, 0x04, 0x99, 0xff, - 0x05, 0x88, 0xd0, 0xf8, 0xa0, 0x00, 0xb1, 0x04, - - 0x38, 0x65, 0x04, 0x85, 0x04, 0x90, 0x23, 0xe6, - 0x05, 0x60, 0xa0, 0x03, 0xb1, 0x04, 0x85, 0x2d, - - 0x88, 0xb1, 0x04, 0x85, 0x2c, 0x88, 0xb1, 0x04, - 0x85, 0x2b, 0x88, 0xb1, 0x04, 0x85, 0x2a, 0x18, - - 0xa5, 0x04, 0x69, 0x04, 0x85, 0x04, 0x90, 0x02, - 0xe6, 0x05, 0x60, 0xa2, 0x37, 0xa0, 0x03, 0xb1, - - 0x04, 0x95, 0x03, 0x88, 0xb1, 0x04, 0x95, 0x02, - 0x88, 0xb1, 0x04, 0x95, 0x01, 0x88, 0xb1, 0x04, - - 0x95, 0x00, 0x18, 0xa5, 0x04, 0x69, 0x04, 0x85, - 0x04, 0x90, 0xdf, 0xe6, 0x05, 0x60, 0x85, 0x04, - - 0xb0, 0x02, 0xc6, 0x05, 0xa4, 0x05, 0xc4, 0x03, - 0x90, 0x07, 0xd0, 0x04, 0xc5, 0x02, 0x90, 0x01, - - 0x60, 0x4c, 0xb7, 0x8c, 0xa5, 0x2a, 0x95, 0x00, - 0xa5, 0x2b, 0x95, 0x01, 0xa5, 0x2c, 0x95, 0x02, - - 0xa5, 0x2d, 0x95, 0x03, 0x60, 0x18, 0x98, 0x65, - 0x3d, 0x85, 0x3d, 0x90, 0x02, 0xe6, 0x3e, 0xa0, - - 0x01, 0x60, 0x20, 0xdd, 0xbe, 0xa8, 0xa9, 0xff, - 0x84, 0x3d, 0xa2, 0x37, 0x20, 0xdd, 0xff, 0xa5, - - 0x18, 0x85, 0x13, 0xa0, 0x00, 0x84, 0x12, 0xc8, - 0x88, 0xb1, 0x12, 0xc9, 0x0d, 0xd0, 0x1f, 0xc8, - - 0xb1, 0x12, 0x30, 0x0c, 0xa0, 0x03, 0xb1, 0x12, - 0xf0, 0x14, 0x18, 0x20, 0x93, 0xbe, 0xd0, 0xe8, - - 0xc8, 0x18, 0x98, 0x65, 0x12, 0x85, 0x12, 0x90, - 0x02, 0xe6, 0x13, 0xa0, 0x01, 0x60, 0x20, 0xcf, - - 0xbf, 0x0d, 0x42, 0x61, 0x64, 0x20, 0x70, 0x72, - 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x0d, 0xea, 0x4c, - - 0xf6, 0x8a, 0xa9, 0x00, 0x85, 0x37, 0xa9, 0x06, - 0x85, 0x38, 0xa4, 0x36, 0xa9, 0x0d, 0x99, 0x00, - - 0x06, 0x60, 0x20, 0xd2, 0xbe, 0xa2, 0x00, 0xa0, - 0x06, 0x20, 0xf7, 0xff, 0x4c, 0x9b, 0x8b, 0x4c, - - 0x0e, 0x8c, 0x20, 0x1d, 0x9b, 0xd0, 0xf8, 0x20, - 0xb2, 0xbe, 0x4c, 0x4c, 0x98, 0x20, 0xd2, 0xbe, - - 0x88, 0x84, 0x39, 0xa5, 0x18, 0x85, 0x3a, 0xa9, - 0x82, 0x20, 0xf4, 0xff, 0x86, 0x3b, 0x84, 0x3c, - - 0xa9, 0x00, 0x60, 0x20, 0x6f, 0xbe, 0xa5, 0x12, - 0x85, 0x45, 0xa5, 0x13, 0x85, 0x46, 0xa9, 0x23, - - 0x85, 0x3d, 0xa9, 0x80, 0x85, 0x3e, 0xa5, 0x18, - 0x85, 0x42, 0x20, 0xdd, 0xbe, 0x86, 0x3f, 0x84, - - 0x40, 0x86, 0x43, 0x84, 0x44, 0x86, 0x47, 0x84, - 0x48, 0x85, 0x41, 0xa8, 0xa2, 0x37, 0x20, 0xdd, - - 0xff, 0x4c, 0x9b, 0x8b, 0x20, 0x62, 0xbe, 0x4c, - 0xf3, 0x8a, 0x20, 0x62, 0xbe, 0x4c, 0x14, 0xbd, - - 0x20, 0xa9, 0xbf, 0x48, 0x20, 0x13, 0x98, 0x20, - 0xee, 0x92, 0x68, 0xa8, 0xa2, 0x2a, 0xa9, 0x01, - - 0x20, 0xda, 0xff, 0x4c, 0x9b, 0x8b, 0x38, 0xa9, - 0x00, 0x2a, 0x2a, 0x48, 0x20, 0xb5, 0xbf, 0xa2, - - 0x2a, 0x68, 0x20, 0xda, 0xff, 0xa9, 0x40, 0x60, - 0x20, 0xa9, 0xbf, 0x48, 0x20, 0xae, 0x8a, 0x20, - - 0x49, 0x98, 0x20, 0xee, 0x92, 0x68, 0xa8, 0xa5, - 0x2a, 0x20, 0xd4, 0xff, 0x4c, 0x9b, 0x8b, 0x20, - - 0xb5, 0xbf, 0x20, 0xd7, 0xff, 0x4c, 0xd8, 0xae, - 0xa9, 0x40, 0xd0, 0x06, 0xa9, 0x80, 0xd0, 0x02, - - 0xa9, 0xc0, 0x48, 0x20, 0xec, 0xad, 0xd0, 0x0e, - 0x20, 0xba, 0xbe, 0xa2, 0x00, 0xa0, 0x06, 0x68, - - 0x20, 0xce, 0xff, 0x4c, 0xd8, 0xae, 0x4c, 0x0e, - 0x8c, 0x20, 0xa9, 0xbf, 0x20, 0x52, 0x98, 0xa4, - - 0x2a, 0xa9, 0x00, 0x20, 0xce, 0xff, 0x4c, 0x9b, - 0x8b, 0xa5, 0x0a, 0x85, 0x1b, 0xa5, 0x0b, 0x85, - - 0x19, 0xa5, 0x0c, 0x85, 0x1a, 0x20, 0x8c, 0x8a, - 0xc9, 0x23, 0xd0, 0x07, 0x20, 0xe3, 0x92, 0xa4, - - 0x2a, 0x98, 0x60, 0x00, 0x2d, 0x4d, 0x69, 0x73, - 0x73, 0x69, 0x6e, 0x67, 0x20, 0x23, 0x00, 0x68, - - 0x85, 0x37, 0x68, 0x85, 0x38, 0xa0, 0x00, 0xf0, - 0x03, 0x20, 0xe3, 0xff, 0x20, 0x4b, 0x89, 0x10, - - 0xf8, 0x6c, 0x37, 0x00, 0x20, 0x57, 0x98, 0x20, - 0x25, 0xbc, 0xa0, 0x01, 0xb1, 0xfd, 0xf0, 0x06, - - 0x20, 0x0e, 0xb5, 0xc8, 0xd0, 0xf6, 0x4c, 0x9b, - 0x8b, 0x00, 0x52, 0x6f, 0x67, 0x65, 0x72, 0x00 +''' +Created on 12 Oct 2011 + +@author: chris.whitworth +''' +rom_os12 = [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x00, + 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x36, 0x36, 0x7f, 0x36, 0x7f, 0x36, 0x36, 0x00, + 0x0c, 0x3f, 0x68, 0x3e, 0x0b, 0x7e, 0x18, 0x00, + 0x60, 0x66, 0x0c, 0x18, 0x30, 0x66, 0x06, 0x00, + 0x38, 0x6c, 0x6c, 0x38, 0x6d, 0x66, 0x3b, 0x00, + 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0c, 0x18, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x00, + 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, + 0x00, 0x18, 0x7e, 0x3c, 0x7e, 0x18, 0x00, 0x00, + 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, + 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, + 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, + 0x3c, 0x66, 0x6e, 0x7e, 0x76, 0x66, 0x3c, 0x00, + 0x18, 0x38, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, + 0x3c, 0x66, 0x06, 0x0c, 0x18, 0x30, 0x7e, 0x00, + 0x3c, 0x66, 0x06, 0x1c, 0x06, 0x66, 0x3c, 0x00, + 0x0c, 0x1c, 0x3c, 0x6c, 0x7e, 0x0c, 0x0c, 0x00, + 0x7e, 0x60, 0x7c, 0x06, 0x06, 0x66, 0x3c, 0x00, + 0x1c, 0x30, 0x60, 0x7c, 0x66, 0x66, 0x3c, 0x00, + 0x7e, 0x06, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x00, + 0x3c, 0x66, 0x66, 0x3c, 0x66, 0x66, 0x3c, 0x00, + 0x3c, 0x66, 0x66, 0x3e, 0x06, 0x0c, 0x38, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x30, + 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, + 0x00, 0x00, 0x7e, 0x00, 0x7e, 0x00, 0x00, 0x00, + 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, + 0x3c, 0x66, 0x0c, 0x18, 0x18, 0x00, 0x18, 0x00, + 0x3c, 0x66, 0x6e, 0x6a, 0x6e, 0x60, 0x3c, 0x00, + 0x3c, 0x66, 0x66, 0x7e, 0x66, 0x66, 0x66, 0x00, + 0x7c, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x7c, 0x00, + 0x3c, 0x66, 0x60, 0x60, 0x60, 0x66, 0x3c, 0x00, + 0x78, 0x6c, 0x66, 0x66, 0x66, 0x6c, 0x78, 0x00, + 0x7e, 0x60, 0x60, 0x7c, 0x60, 0x60, 0x7e, 0x00, + 0x7e, 0x60, 0x60, 0x7c, 0x60, 0x60, 0x60, 0x00, + 0x3c, 0x66, 0x60, 0x6e, 0x66, 0x66, 0x3c, 0x00, + 0x66, 0x66, 0x66, 0x7e, 0x66, 0x66, 0x66, 0x00, + 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, + 0x3e, 0x0c, 0x0c, 0x0c, 0x0c, 0x6c, 0x38, 0x00, + 0x66, 0x6c, 0x78, 0x70, 0x78, 0x6c, 0x66, 0x00, + 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x7e, 0x00, + 0x63, 0x77, 0x7f, 0x6b, 0x6b, 0x63, 0x63, 0x00, + + 0x66, 0x66, 0x76, 0x7e, 0x6e, 0x66, 0x66, 0x00, + 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, + + 0x7c, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x00, + 0x3c, 0x66, 0x66, 0x66, 0x6a, 0x6c, 0x36, 0x00, + + 0x7c, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0x00, + 0x3c, 0x66, 0x60, 0x3c, 0x06, 0x66, 0x3c, 0x00, + + 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, + + 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x00, + 0x63, 0x63, 0x6b, 0x6b, 0x7f, 0x77, 0x63, 0x00, + + 0x66, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0x66, 0x00, + 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x00, + + 0x7e, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x7e, 0x00, + 0x7c, 0x60, 0x60, 0x60, 0x60, 0x60, 0x7c, 0x00, + + 0x00, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x00, 0x00, + 0x3e, 0x06, 0x06, 0x06, 0x06, 0x06, 0x3e, 0x00, + + 0x18, 0x3c, 0x66, 0x42, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + + 0x1c, 0x36, 0x30, 0x7c, 0x30, 0x30, 0x7e, 0x00, + 0x00, 0x00, 0x3c, 0x06, 0x3e, 0x66, 0x3e, 0x00, + + 0x60, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x7c, 0x00, + 0x00, 0x00, 0x3c, 0x66, 0x60, 0x66, 0x3c, 0x00, + + 0x06, 0x06, 0x3e, 0x66, 0x66, 0x66, 0x3e, 0x00, + 0x00, 0x00, 0x3c, 0x66, 0x7e, 0x60, 0x3c, 0x00, + + 0x1c, 0x30, 0x30, 0x7c, 0x30, 0x30, 0x30, 0x00, + 0x00, 0x00, 0x3e, 0x66, 0x66, 0x3e, 0x06, 0x3c, + + 0x60, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x00, + 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00, + + 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x70, + 0x60, 0x60, 0x66, 0x6c, 0x78, 0x6c, 0x66, 0x00, + + 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, + 0x00, 0x00, 0x36, 0x7f, 0x6b, 0x6b, 0x63, 0x00, + + 0x00, 0x00, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x00, + 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x00, + + 0x00, 0x00, 0x7c, 0x66, 0x66, 0x7c, 0x60, 0x60, + 0x00, 0x00, 0x3e, 0x66, 0x66, 0x3e, 0x06, 0x07, + + 0x00, 0x00, 0x6c, 0x76, 0x60, 0x60, 0x60, 0x00, + 0x00, 0x00, 0x3e, 0x60, 0x3c, 0x06, 0x7c, 0x00, + + 0x30, 0x30, 0x7c, 0x30, 0x30, 0x30, 0x1c, 0x00, + 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x00, + + 0x00, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x00, + 0x00, 0x00, 0x63, 0x6b, 0x6b, 0x7f, 0x36, 0x00, + + 0x00, 0x00, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0x00, + 0x00, 0x00, 0x66, 0x66, 0x66, 0x3e, 0x06, 0x3c, + + 0x00, 0x00, 0x7e, 0x0c, 0x18, 0x30, 0x7e, 0x00, + 0x0c, 0x18, 0x18, 0x70, 0x18, 0x18, 0x0c, 0x00, + + 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00, + 0x30, 0x18, 0x18, 0x0e, 0x18, 0x18, 0x30, 0x00, + + 0x31, 0x6b, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + + 0x4c, 0x1d, 0xcb, 0x0d, 0x42, 0x42, 0x43, 0x20, + 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x72, + + 0x20, 0x00, 0x31, 0x36, 0x4b, 0x07, 0x00, 0x33, + 0x32, 0x4b, 0x07, 0x00, 0x08, 0x0d, 0x0d, 0x00, + + 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, + 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00, + + 0x55, 0xaa, 0xff, 0x11, 0x3b, 0x96, 0xa1, 0xad, + 0xb9, 0x11, 0x6f, 0xc5, 0x64, 0xf0, 0x5b, 0x59, + + 0xaf, 0x8d, 0xa6, 0xc0, 0xf9, 0xfd, 0x92, 0x39, + 0x9b, 0xeb, 0xf1, 0x39, 0x8c, 0xbd, 0x11, 0xfa, + + 0xa2, 0x79, 0x87, 0xac, 0xc5, 0x2f, 0xc5, 0xc5, + 0xc5, 0xc5, 0xc5, 0xe8, 0xc5, 0xc6, 0xc6, 0xc6, + + 0xc7, 0xc7, 0xc5, 0xc5, 0xc7, 0x4f, 0x4e, 0x5b, + 0xc8, 0xc5, 0x5f, 0x57, 0x78, 0x6b, 0xc9, 0xc5, + + 0x3c, 0x7c, 0xc7, 0x4e, 0xca, 0x00, 0x00, 0x02, + 0x80, 0x05, 0x00, 0x07, 0x80, 0x0a, 0x00, 0x0c, + + 0x80, 0x0f, 0x00, 0x11, 0x80, 0x14, 0x00, 0x16, + 0x80, 0x19, 0x00, 0x1b, 0x80, 0x1e, 0x00, 0x20, + + 0x80, 0x23, 0x00, 0x25, 0x80, 0x28, 0x00, 0x2a, + 0x80, 0x2d, 0x00, 0x2f, 0x80, 0x32, 0x00, 0x34, + + 0x80, 0x37, 0x00, 0x39, 0x80, 0x3c, 0x00, 0x3e, + 0x80, 0x41, 0x00, 0x43, 0x80, 0x46, 0x00, 0x48, + + 0x80, 0x4b, 0x00, 0x4d, 0x80, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x50, 0x00, 0x78, 0x00, 0xa0, 0x00, + + 0xc8, 0x00, 0xf0, 0x01, 0x18, 0x01, 0x40, 0x01, + 0x68, 0x01, 0x90, 0x01, 0xb8, 0x01, 0xe0, 0x02, + + 0x08, 0x02, 0x30, 0x02, 0x58, 0x02, 0x80, 0x02, + 0xa8, 0x02, 0xd0, 0x02, 0xf8, 0x03, 0x20, 0x03, + + 0x48, 0x03, 0x70, 0x03, 0x98, 0x03, 0xc0, 0x1f, + 0x1f, 0x1f, 0x18, 0x1f, 0x1f, 0x18, 0x18, 0x4f, + + 0x27, 0x13, 0x4f, 0x27, 0x13, 0x27, 0x27, 0x9c, + 0xd8, 0xf4, 0x9c, 0x88, 0xc4, 0x88, 0x4b, 0x08, + + 0x10, 0x20, 0x08, 0x08, 0x10, 0x08, 0x01, 0xaa, + 0x55, 0x88, 0x44, 0x22, 0x11, 0x80, 0x40, 0x20, + + 0x10, 0x08, 0x04, 0x02, 0x01, 0x03, 0x0f, 0x01, + 0x01, 0x03, 0x01, 0x00, 0xff, 0x00, 0x00, 0xff, + + 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x0f, + 0xf0, 0xff, 0x00, 0x03, 0x0c, 0x0f, 0x30, 0x33, + + 0x3c, 0x3f, 0xc0, 0xc3, 0xcc, 0xcf, 0xf0, 0xf3, + 0xfc, 0xff, 0x07, 0x03, 0x01, 0x00, 0x07, 0x03, + + 0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0x03, 0x04, + 0x00, 0x06, 0x02, 0x0d, 0x05, 0x0d, 0x05, 0x04, + + 0x04, 0x0c, 0x0c, 0x04, 0x02, 0x32, 0x7a, 0x92, + 0xe6, 0x50, 0x40, 0x28, 0x20, 0x04, 0x30, 0x40, + + 0x58, 0x60, 0x7c, 0x28, 0x40, 0x80, 0xb5, 0x75, + 0x75, 0x0b, 0x17, 0x23, 0x2f, 0x3b, 0x7f, 0x50, + + 0x62, 0x28, 0x26, 0x00, 0x20, 0x22, 0x01, 0x07, + 0x67, 0x08, 0x7f, 0x50, 0x62, 0x28, 0x1e, 0x02, + + 0x19, 0x1b, 0x01, 0x09, 0x67, 0x09, 0x3f, 0x28, + 0x31, 0x24, 0x26, 0x00, 0x20, 0x22, 0x01, 0x07, + + 0x67, 0x08, 0x3f, 0x28, 0x31, 0x24, 0x1e, 0x02, + 0x19, 0x1b, 0x01, 0x09, 0x67, 0x09, 0x3f, 0x28, + + 0x33, 0x24, 0x1e, 0x02, 0x19, 0x1b, 0x93, 0x12, + 0x72, 0x13, 0x86, 0xd3, 0x7e, 0xd3, 0x6a, 0x74, + + 0x42, 0x4b, 0xd3, 0xd3, 0xd3, 0xd3, 0x23, 0x5f, + 0x60, 0x23, 0x04, 0x05, 0x06, 0x00, 0x01, 0x02, + + 0xae, 0x6a, 0x02, 0xd0, 0x4d, 0x24, 0xd0, 0x50, + 0x0f, 0x20, 0x68, 0xc5, 0x20, 0x6a, 0xcd, 0x30, + + 0x07, 0xc9, 0x0d, 0xd0, 0x03, 0x20, 0x18, 0xd9, + 0xc9, 0x7f, 0xf0, 0x11, 0xc9, 0x20, 0x90, 0x0f, + + 0x24, 0xd0, 0x30, 0x06, 0x20, 0xb7, 0xcf, 0x20, + 0x64, 0xc6, 0x4c, 0x5e, 0xc5, 0xa9, 0x20, 0xa8, + + 0xb9, 0x33, 0xc3, 0x8d, 0x5d, 0x03, 0xb9, 0x54, + 0xc3, 0x30, 0x4a, 0xaa, 0x09, 0xf0, 0x8d, 0x6a, + + 0x02, 0x8a, 0x4a, 0x4a, 0x4a, 0x4a, 0x18, 0x69, + 0xc3, 0x8d, 0x5e, 0x03, 0x24, 0xd0, 0x70, 0x1f, + + 0x18, 0x60, 0x9d, 0x24, 0x02, 0xe8, 0x8e, 0x6a, + 0x02, 0xd0, 0x17, 0x24, 0xd0, 0x30, 0x15, 0x70, + + 0x05, 0x20, 0xf5, 0xcc, 0x18, 0x60, 0x20, 0x68, + 0xc5, 0x20, 0x6a, 0xcd, 0x20, 0xf5, 0xcc, 0x20, + + 0x65, 0xc5, 0x18, 0x60, 0xac, 0x5e, 0x03, 0xc0, + 0xc5, 0xd0, 0xf7, 0xaa, 0xa5, 0xd0, 0x4a, 0x90, + + 0xd0, 0x8a, 0x4c, 0x1e, 0xe1, 0x8d, 0x5e, 0x03, + 0x98, 0xc9, 0x08, 0x90, 0x06, 0x49, 0xff, 0xc9, + + 0xf2, 0x49, 0xff, 0x24, 0xd0, 0x30, 0x29, 0x08, + 0x20, 0xf5, 0xcc, 0x28, 0x90, 0x03, 0xa5, 0xd0, + + 0x4a, 0x24, 0xd0, 0x50, 0xac, 0x20, 0x7a, 0xcd, + 0x08, 0x48, 0xa2, 0x18, 0xa0, 0x64, 0x20, 0xde, + + 0xcd, 0x20, 0x06, 0xcf, 0x20, 0x02, 0xca, 0xa5, + 0xd0, 0x49, 0x02, 0x85, 0xd0, 0x68, 0x28, 0x60, + + 0x49, 0x06, 0xd0, 0x08, 0xa9, 0x7f, 0x90, 0x20, + 0xa5, 0xd0, 0x29, 0x20, 0x60, 0xa0, 0x00, 0x8c, + + 0x69, 0x02, 0xa9, 0x04, 0xd0, 0x07, 0x20, 0xa2, + 0xe1, 0xa9, 0x94, 0x49, 0x95, 0x05, 0xd0, 0xd0, + + 0x09, 0x20, 0xa2, 0xe1, 0xa9, 0x0a, 0x49, 0xf4, + 0x25, 0xd0, 0x85, 0xd0, 0x60, 0xad, 0x61, 0x03, + + 0xf0, 0xfa, 0x20, 0x51, 0xc9, 0xa9, 0xdf, 0xd0, + 0xef, 0xad, 0x61, 0x03, 0xf0, 0xee, 0xa9, 0x20, + + 0x20, 0x54, 0xc9, 0xd0, 0xd8, 0x20, 0x88, 0xc5, + 0xd0, 0x55, 0xce, 0x18, 0x03, 0xae, 0x18, 0x03, + + 0xec, 0x08, 0x03, 0x30, 0x19, 0xad, 0x4a, 0x03, + 0x38, 0xed, 0x4f, 0x03, 0xaa, 0xad, 0x4b, 0x03, + + 0xe9, 0x00, 0xcd, 0x4e, 0x03, 0xb0, 0x03, 0x6d, + 0x54, 0x03, 0xa8, 0x4c, 0xf6, 0xc9, 0xad, 0x0a, + + 0x03, 0x8d, 0x18, 0x03, 0xce, 0x69, 0x02, 0x10, + 0x03, 0xee, 0x69, 0x02, 0xae, 0x19, 0x03, 0xec, + + 0x0b, 0x03, 0xf0, 0x06, 0xce, 0x19, 0x03, 0x4c, + 0xaf, 0xc6, 0x18, 0x20, 0x3f, 0xcd, 0xa9, 0x08, + + 0x24, 0xd0, 0xd0, 0x05, 0x20, 0x94, 0xc9, 0xd0, + 0x03, 0x20, 0xa4, 0xcd, 0x4c, 0xac, 0xc6, 0xa2, + + 0x00, 0x86, 0xdb, 0x20, 0x0d, 0xd1, 0xa6, 0xdb, + 0x38, 0xbd, 0x24, 0x03, 0xe9, 0x08, 0x9d, 0x24, + + 0x03, 0xb0, 0x03, 0xde, 0x25, 0x03, 0xa5, 0xda, + 0xd0, 0x1e, 0x20, 0x0d, 0xd1, 0xf0, 0x19, 0xa6, + + 0xdb, 0xbd, 0x04, 0x03, 0xe0, 0x01, 0xb0, 0x02, + 0xe9, 0x06, 0x9d, 0x24, 0x03, 0xbd, 0x05, 0x03, + + 0xe9, 0x00, 0x9d, 0x25, 0x03, 0x8a, 0xf0, 0x08, + 0x4c, 0xb8, 0xd1, 0x20, 0x88, 0xc5, 0xf0, 0x94, + + 0xa2, 0x02, 0xd0, 0x52, 0xa5, 0xd0, 0x29, 0x20, + 0xd0, 0x4a, 0xae, 0x18, 0x03, 0xec, 0x0a, 0x03, + + 0xb0, 0x12, 0xee, 0x18, 0x03, 0xad, 0x4a, 0x03, + 0x6d, 0x4f, 0x03, 0xaa, 0xad, 0x4b, 0x03, 0x69, + + 0x00, 0x4c, 0xf6, 0xc9, 0xad, 0x08, 0x03, 0x8d, + 0x18, 0x03, 0x18, 0x20, 0xe3, 0xca, 0xae, 0x19, + + 0x03, 0xec, 0x09, 0x03, 0xb0, 0x05, 0xee, 0x19, + 0x03, 0x90, 0x14, 0x20, 0x3f, 0xcd, 0xa9, 0x08, + + 0x24, 0xd0, 0xd0, 0x05, 0x20, 0xa4, 0xc9, 0xd0, + 0x03, 0x20, 0xff, 0xcd, 0x20, 0xac, 0xce, 0x20, + + 0x06, 0xcf, 0x90, 0x7e, 0xa2, 0x00, 0x86, 0xdb, + 0x20, 0x0d, 0xd1, 0xa6, 0xdb, 0x18, 0xbd, 0x24, + + 0x03, 0x69, 0x08, 0x9d, 0x24, 0x03, 0x90, 0x03, + 0xfe, 0x25, 0x03, 0xa5, 0xda, 0xd0, 0x89, 0x20, + + 0x0d, 0xd1, 0xf0, 0x84, 0xa6, 0xdb, 0xbd, 0x00, + 0x03, 0xe0, 0x01, 0x90, 0x02, 0x69, 0x06, 0x9d, + + 0x24, 0x03, 0xbd, 0x01, 0x03, 0x69, 0x00, 0x9d, + 0x25, 0x03, 0x8a, 0xf0, 0x08, 0x4c, 0xb8, 0xd1, + + 0x20, 0x88, 0xc5, 0xf0, 0x95, 0xa2, 0x02, 0x4c, + 0x21, 0xc6, 0xae, 0x55, 0x03, 0xad, 0x21, 0x03, + + 0xcd, 0x23, 0x03, 0x90, 0x53, 0xdd, 0xe7, 0xc3, + 0xf0, 0x02, 0xb0, 0x4c, 0xad, 0x22, 0x03, 0xa8, + + 0xdd, 0xef, 0xc3, 0xf0, 0x02, 0xb0, 0x41, 0x38, + 0xed, 0x20, 0x03, 0x30, 0x3b, 0xa8, 0x20, 0x88, + + 0xca, 0xa9, 0x08, 0x20, 0x9d, 0xc5, 0xa2, 0x20, + 0xa0, 0x08, 0x20, 0x8a, 0xd4, 0x20, 0xe8, 0xce, + + 0xb0, 0x47, 0x4c, 0x02, 0xca, 0xa0, 0x03, 0xb1, + 0xf0, 0x99, 0x28, 0x03, 0x88, 0x10, 0xf8, 0xa9, + + 0x28, 0x20, 0x39, 0xd8, 0xa0, 0x04, 0xd0, 0x08, + 0x2d, 0x60, 0x03, 0xaa, 0xbd, 0x6f, 0x03, 0xc8, + + 0x91, 0xf0, 0xa9, 0x00, 0xc0, 0x04, 0xd0, 0xf7, + 0x60, 0x20, 0x88, 0xc5, 0xd0, 0x5f, 0xa5, 0xd0, + + 0x29, 0x08, 0xd0, 0x03, 0x4c, 0xc1, 0xcb, 0xae, + 0x0b, 0x03, 0x8e, 0x19, 0x03, 0x20, 0xac, 0xce, + + 0xae, 0x19, 0x03, 0xec, 0x09, 0x03, 0xe8, 0x90, + 0xf1, 0x20, 0x88, 0xc5, 0xf0, 0x03, 0x4c, 0xa6, + + 0xcf, 0x8d, 0x23, 0x03, 0x8d, 0x22, 0x03, 0x20, + 0x88, 0xc5, 0xd0, 0xcc, 0x20, 0xa8, 0xc7, 0x18, + + 0xad, 0x22, 0x03, 0x6d, 0x08, 0x03, 0x8d, 0x18, + 0x03, 0xad, 0x23, 0x03, 0x18, 0x6d, 0x0b, 0x03, + + 0x8d, 0x19, 0x03, 0x20, 0xe8, 0xce, 0x90, 0x8a, + 0xa2, 0x18, 0xa0, 0x28, 0x4c, 0xde, 0xcd, 0x20, + + 0x88, 0xc5, 0xf0, 0x03, 0x4c, 0xad, 0xcf, 0x20, + 0x6e, 0xce, 0x4c, 0xaf, 0xc6, 0x20, 0xa6, 0xcf, + + 0xad, 0x61, 0x03, 0xf0, 0x33, 0xae, 0x5a, 0x03, + 0xac, 0x5c, 0x03, 0x20, 0xb3, 0xd0, 0xa2, 0x00, + + 0xa0, 0x28, 0x20, 0x7c, 0xd4, 0x38, 0xad, 0x06, + 0x03, 0xed, 0x02, 0x03, 0xa8, 0xc8, 0x8c, 0x30, + + 0x03, 0xa2, 0x2c, 0xa0, 0x28, 0x20, 0xa6, 0xd6, + 0xad, 0x2e, 0x03, 0xd0, 0x03, 0xce, 0x2f, 0x03, + + 0xce, 0x2e, 0x03, 0xce, 0x30, 0x03, 0xd0, 0xe9, + 0x60, 0xa0, 0x00, 0xf0, 0x02, 0xa0, 0x02, 0xad, + + 0x23, 0x03, 0x10, 0x01, 0xc8, 0x2d, 0x60, 0x03, + 0x85, 0xda, 0xad, 0x60, 0x03, 0xf0, 0x1c, 0x29, + + 0x07, 0x18, 0x65, 0xda, 0xaa, 0xbd, 0x23, 0xc4, + 0x99, 0x57, 0x03, 0xc0, 0x02, 0xb0, 0x0d, 0xad, + + 0x57, 0x03, 0x49, 0xff, 0x85, 0xd3, 0x4d, 0x58, + 0x03, 0x85, 0xd2, 0x60, 0xad, 0x22, 0x03, 0x99, + + 0x59, 0x03, 0x60, 0xa9, 0x20, 0x8d, 0x58, 0x03, + 0x60, 0xa2, 0x05, 0xa9, 0x00, 0x9d, 0x57, 0x03, + + 0xca, 0x10, 0xfa, 0xae, 0x60, 0x03, 0xf0, 0xeb, + 0xa9, 0xff, 0xe0, 0x0f, 0xd0, 0x02, 0xa9, 0x3f, + + 0x8d, 0x57, 0x03, 0x8d, 0x59, 0x03, 0x49, 0xff, + 0x85, 0xd2, 0x85, 0xd3, 0x8e, 0x1f, 0x03, 0xe0, + + 0x03, 0xf0, 0x11, 0x90, 0x20, 0x8e, 0x20, 0x03, + 0x20, 0x92, 0xc8, 0xce, 0x20, 0x03, 0xce, 0x1f, + + 0x03, 0x10, 0xf5, 0x60, 0xa2, 0x07, 0x8e, 0x20, + 0x03, 0x20, 0x92, 0xc8, 0x4e, 0x20, 0x03, 0xce, + + 0x1f, 0x03, 0x10, 0xf5, 0x60, 0xa2, 0x07, 0x20, + 0x8f, 0xc8, 0xa2, 0x00, 0x8e, 0x1f, 0x03, 0x8e, + + 0x20, 0x03, 0x08, 0x78, 0xad, 0x1f, 0x03, 0x2d, + 0x60, 0x03, 0xaa, 0xad, 0x20, 0x03, 0x29, 0x0f, + + 0x9d, 0x6f, 0x03, 0xa8, 0xad, 0x60, 0x03, 0x85, + 0xfa, 0xc9, 0x03, 0x08, 0x8a, 0x6a, 0x66, 0xfa, + + 0xb0, 0xfb, 0x06, 0xfa, 0x98, 0x05, 0xfa, 0xaa, + 0xa0, 0x00, 0x28, 0x08, 0xd0, 0x0e, 0x29, 0x60, + + 0xf0, 0x09, 0xc9, 0x60, 0xf0, 0x05, 0x8a, 0x49, + 0x60, 0xd0, 0x01, 0x8a, 0x20, 0x11, 0xea, 0x98, + + 0x38, 0x6d, 0x60, 0x03, 0xa8, 0x8a, 0x69, 0x10, + 0xaa, 0xc0, 0x10, 0x90, 0xdd, 0x28, 0x28, 0x60, + + 0x08, 0x2d, 0x60, 0x03, 0xaa, 0xc8, 0xb1, 0xf0, + 0x4c, 0x9e, 0xc8, 0xad, 0x23, 0x03, 0x4c, 0x33, + + 0xcb, 0xad, 0x1b, 0x03, 0xc9, 0x20, 0x90, 0x47, + 0x48, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0xaa, 0xbd, + + 0x0d, 0xc4, 0x2c, 0x67, 0x03, 0xd0, 0x20, 0x0d, + 0x67, 0x03, 0x8d, 0x67, 0x03, 0x8a, 0x29, 0x03, + + 0x18, 0x69, 0xbf, 0x85, 0xdf, 0xbd, 0x67, 0x03, + 0x85, 0xdd, 0xa0, 0x00, 0x84, 0xdc, 0x84, 0xde, + + 0xb1, 0xde, 0x91, 0xdc, 0x88, 0xd0, 0xf9, 0x68, + 0x20, 0x3e, 0xd0, 0xa0, 0x07, 0xb9, 0x1c, 0x03, + + 0x91, 0xde, 0x88, 0x10, 0xf8, 0x60, 0x68, 0x60, + 0xad, 0x1f, 0x03, 0x18, 0x6c, 0x26, 0x02, 0xc9, + + 0x01, 0x90, 0x15, 0xd0, 0xf7, 0x20, 0x88, 0xc5, + 0xd0, 0xed, 0xa9, 0x20, 0xac, 0x1c, 0x03, 0xf0, + + 0x03, 0xad, 0x5f, 0x03, 0xa0, 0x0a, 0xd0, 0x2d, + 0xad, 0x1d, 0x03, 0xac, 0x1c, 0x03, 0xc0, 0x07, + + 0x90, 0x23, 0xd0, 0x03, 0x6d, 0x90, 0x02, 0xc0, + 0x08, 0xd0, 0x07, 0x09, 0x00, 0x30, 0x03, 0x4d, + + 0x91, 0x02, 0xc0, 0x0a, 0xd0, 0x0f, 0x8d, 0x5f, + 0x03, 0xa8, 0xa5, 0xd0, 0x29, 0x20, 0x08, 0x98, + + 0xa0, 0x0a, 0x28, 0xd0, 0x06, 0x8c, 0x00, 0xfe, + 0x8d, 0x01, 0xfe, 0x60, 0xae, 0x61, 0x03, 0xf0, + + 0xa7, 0x4c, 0x60, 0xd0, 0xae, 0x50, 0x03, 0xad, + 0x51, 0x03, 0x20, 0xf8, 0xcc, 0xb0, 0x14, 0x6d, + + 0x54, 0x03, 0x90, 0x0f, 0xae, 0x50, 0x03, 0xad, + 0x51, 0x03, 0x20, 0xd4, 0xca, 0x10, 0x04, 0x38, + + 0xed, 0x54, 0x03, 0x8d, 0x51, 0x03, 0x8e, 0x50, + 0x03, 0xa0, 0x0c, 0xd0, 0x51, 0xa9, 0x00, 0xa2, + + 0x2c, 0x9d, 0x00, 0x03, 0xca, 0x10, 0xfa, 0xae, + 0x55, 0x03, 0xbc, 0xef, 0xc3, 0x8c, 0x0a, 0x03, + + 0x20, 0x88, 0xca, 0xbc, 0xe7, 0xc3, 0x8c, 0x09, + 0x03, 0xa0, 0x03, 0x8c, 0x23, 0x03, 0xc8, 0x8c, + + 0x21, 0x03, 0xce, 0x22, 0x03, 0xce, 0x20, 0x03, + 0x20, 0x39, 0xca, 0xa9, 0xf7, 0x20, 0xa8, 0xc5, + + 0xae, 0x50, 0x03, 0xad, 0x51, 0x03, 0x8e, 0x4a, + 0x03, 0x8d, 0x4b, 0x03, 0x10, 0x04, 0x38, 0xed, + + 0x54, 0x03, 0x86, 0xd8, 0x85, 0xd9, 0xae, 0x4a, + 0x03, 0xad, 0x4b, 0x03, 0xa0, 0x0e, 0x48, 0xad, + + 0x55, 0x03, 0xc9, 0x07, 0x68, 0xb0, 0x10, 0x86, + 0xda, 0x4a, 0x66, 0xda, 0x4a, 0x66, 0xda, 0x4a, + + 0x66, 0xda, 0xa6, 0xda, 0x4c, 0x2b, 0xca, 0xe9, + 0x74, 0x49, 0x20, 0x8c, 0x00, 0xfe, 0x8d, 0x01, + + 0xfe, 0xc8, 0x8c, 0x00, 0xfe, 0x8e, 0x01, 0xfe, + 0x60, 0x20, 0x81, 0xca, 0xa2, 0x1c, 0xa0, 0x2c, + + 0x20, 0x11, 0xd4, 0x0d, 0x2d, 0x03, 0x30, 0x39, + 0xa2, 0x20, 0x20, 0x49, 0xd1, 0xa2, 0x1c, 0x20, + + 0x49, 0xd1, 0xad, 0x1f, 0x03, 0x0d, 0x1d, 0x03, + 0x30, 0x27, 0xad, 0x23, 0x03, 0xd0, 0x22, 0xae, + + 0x55, 0x03, 0xad, 0x21, 0x03, 0x85, 0xda, 0xad, + 0x20, 0x03, 0x46, 0xda, 0x6a, 0x46, 0xda, 0xd0, + + 0x10, 0x6a, 0x4a, 0xdd, 0xef, 0xc3, 0xf0, 0x02, + 0x10, 0x07, 0xa0, 0x00, 0xa2, 0x1c, 0x20, 0x7c, + + 0xd4, 0xa2, 0x10, 0xa0, 0x28, 0x4c, 0xe6, 0xcd, + 0xc8, 0x98, 0xa0, 0x00, 0x8c, 0x4d, 0x03, 0x8d, + + 0x4c, 0x03, 0xad, 0x4f, 0x03, 0x4a, 0xf0, 0x09, + 0x0e, 0x4c, 0x03, 0x2e, 0x4d, 0x03, 0x4a, 0x90, + + 0xf7, 0x60, 0xa2, 0x20, 0xa0, 0x0c, 0x20, 0x8a, + 0xd4, 0x4c, 0xb8, 0xd1, 0x20, 0xc5, 0xc5, 0x20, + + 0x88, 0xc5, 0xd0, 0x13, 0xae, 0x60, 0x03, 0xf0, + 0x09, 0x85, 0xde, 0xa9, 0xc0, 0x85, 0xdf, 0x4c, + + 0xbf, 0xcf, 0xa9, 0x20, 0x4c, 0xdc, 0xcf, 0xa9, + 0x7f, 0x20, 0x3e, 0xd0, 0xae, 0x5a, 0x03, 0xa0, + + 0x00, 0x4c, 0x63, 0xcf, 0x48, 0x8a, 0x18, 0x6d, + 0x52, 0x03, 0xaa, 0x68, 0x6d, 0x53, 0x03, 0x60, + + 0x20, 0x14, 0xcb, 0x20, 0xd9, 0xe9, 0x90, 0x02, + 0x30, 0xf6, 0xa5, 0xd0, 0x49, 0x04, 0x29, 0x46, + + 0xd0, 0x2a, 0xad, 0x69, 0x02, 0x30, 0x22, 0xad, + 0x19, 0x03, 0xcd, 0x09, 0x03, 0x90, 0x1a, 0x4a, + + 0x4a, 0x38, 0x6d, 0x69, 0x02, 0x6d, 0x0b, 0x03, + 0xcd, 0x09, 0x03, 0x90, 0x0c, 0x18, 0x20, 0xd9, + + 0xe9, 0x38, 0x10, 0xfa, 0xa9, 0xff, 0x8d, 0x69, + 0x02, 0xee, 0x69, 0x02, 0x60, 0x48, 0xa2, 0x7f, + + 0xa9, 0x00, 0x85, 0xd0, 0x9d, 0xff, 0x02, 0xca, + 0xd0, 0xfa, 0x20, 0x07, 0xcd, 0x68, 0xa2, 0x7f, + + 0x8e, 0x66, 0x03, 0x2c, 0x8e, 0x02, 0x30, 0x02, + 0x09, 0x04, 0x29, 0x07, 0xaa, 0x8e, 0x55, 0x03, + + 0xbd, 0x14, 0xc4, 0x8d, 0x60, 0x03, 0xbd, 0xff, + 0xc3, 0x8d, 0x4f, 0x03, 0xbd, 0x3a, 0xc4, 0x8d, + + 0x61, 0x03, 0xd0, 0x02, 0xa9, 0x07, 0x0a, 0xa8, + 0xb9, 0x06, 0xc4, 0x8d, 0x63, 0x03, 0x0a, 0x10, + + 0xfd, 0x8d, 0x62, 0x03, 0xbc, 0x40, 0xc4, 0x8c, + 0x56, 0x03, 0xb9, 0x4f, 0xc4, 0x20, 0xf8, 0xe9, + + 0xb9, 0x4b, 0xc4, 0x20, 0xf8, 0xe9, 0xb9, 0x59, + 0xc4, 0x8d, 0x54, 0x03, 0xb9, 0x5e, 0xc4, 0x8d, + + 0x4e, 0x03, 0x98, 0x69, 0x02, 0x49, 0x07, 0x4a, + 0xaa, 0xbd, 0x66, 0xc4, 0x85, 0xe0, 0xa9, 0xc3, + + 0x85, 0xe1, 0xbd, 0x63, 0xc4, 0x8d, 0x52, 0x03, + 0x8e, 0x53, 0x03, 0xa9, 0x43, 0x20, 0xa8, 0xc5, + + 0xae, 0x55, 0x03, 0xbd, 0xf7, 0xc3, 0x20, 0x00, + 0xea, 0x08, 0x78, 0xbe, 0x69, 0xc4, 0xa0, 0x0b, + + 0xbd, 0x6e, 0xc4, 0x20, 0x5e, 0xc9, 0xca, 0x88, + 0x10, 0xf6, 0x28, 0x20, 0x39, 0xc8, 0x20, 0xbd, + + 0xc9, 0xa2, 0x00, 0xad, 0x4e, 0x03, 0x8e, 0x50, + 0x03, 0x8d, 0x51, 0x03, 0x20, 0xf6, 0xc9, 0xa0, + + 0x0c, 0x20, 0x2b, 0xca, 0xad, 0x58, 0x03, 0xae, + 0x56, 0x03, 0xbc, 0x54, 0xc4, 0x8c, 0x5d, 0x03, + + 0xa0, 0xcc, 0x8c, 0x5e, 0x03, 0xa2, 0x00, 0x8e, + 0x69, 0x02, 0x8e, 0x18, 0x03, 0x8e, 0x19, 0x03, + + 0x6c, 0x5d, 0x03, 0x20, 0x3e, 0xd0, 0xa0, 0x00, + 0xb1, 0xde, 0xc8, 0x91, 0xf0, 0xc0, 0x08, 0xd0, + + 0xf7, 0x60, 0x9d, 0x00, 0x30, 0x9d, 0x00, 0x31, + 0x9d, 0x00, 0x32, 0x9d, 0x00, 0x33, 0x9d, 0x00, + + 0x34, 0x9d, 0x00, 0x35, 0x9d, 0x00, 0x36, 0x9d, + 0x00, 0x37, 0x9d, 0x00, 0x38, 0x9d, 0x00, 0x39, + + 0x9d, 0x00, 0x3a, 0x9d, 0x00, 0x3b, 0x9d, 0x00, + 0x3c, 0x9d, 0x00, 0x3d, 0x9d, 0x00, 0x3e, 0x9d, + + 0x00, 0x3f, 0x9d, 0x00, 0x40, 0x9d, 0x00, 0x41, + 0x9d, 0x00, 0x42, 0x9d, 0x00, 0x43, 0x9d, 0x00, + + 0x44, 0x9d, 0x00, 0x45, 0x9d, 0x00, 0x46, 0x9d, + 0x00, 0x47, 0x9d, 0x00, 0x48, 0x9d, 0x00, 0x49, + + 0x9d, 0x00, 0x4a, 0x9d, 0x00, 0x4b, 0x9d, 0x00, + 0x4c, 0x9d, 0x00, 0x4d, 0x9d, 0x00, 0x4e, 0x9d, + + 0x00, 0x4f, 0x9d, 0x00, 0x50, 0x9d, 0x00, 0x51, + 0x9d, 0x00, 0x52, 0x9d, 0x00, 0x53, 0x9d, 0x00, + + 0x54, 0x9d, 0x00, 0x55, 0x9d, 0x00, 0x56, 0x9d, + 0x00, 0x57, 0x9d, 0x00, 0x58, 0x9d, 0x00, 0x59, + + 0x9d, 0x00, 0x5a, 0x9d, 0x00, 0x5b, 0x9d, 0x00, + 0x5c, 0x9d, 0x00, 0x5d, 0x9d, 0x00, 0x5e, 0x9d, + + 0x00, 0x5f, 0x9d, 0x00, 0x60, 0x9d, 0x00, 0x61, + 0x9d, 0x00, 0x62, 0x9d, 0x00, 0x63, 0x9d, 0x00, + + 0x64, 0x9d, 0x00, 0x65, 0x9d, 0x00, 0x66, 0x9d, + 0x00, 0x67, 0x9d, 0x00, 0x68, 0x9d, 0x00, 0x69, + + 0x9d, 0x00, 0x6a, 0x9d, 0x00, 0x6b, 0x9d, 0x00, + 0x6c, 0x9d, 0x00, 0x6d, 0x9d, 0x00, 0x6e, 0x9d, + + 0x00, 0x6f, 0x9d, 0x00, 0x70, 0x9d, 0x00, 0x71, + 0x9d, 0x00, 0x72, 0x9d, 0x00, 0x73, 0x9d, 0x00, + + 0x74, 0x9d, 0x00, 0x75, 0x9d, 0x00, 0x76, 0x9d, + 0x00, 0x77, 0x9d, 0x00, 0x78, 0x9d, 0x00, 0x79, + + 0x9d, 0x00, 0x7a, 0x9d, 0x00, 0x7b, 0x9d, 0x00, + 0x7c, 0x9d, 0x00, 0x7d, 0x9d, 0x00, 0x7e, 0x9d, + + 0x00, 0x7f, 0xe8, 0xf0, 0x70, 0x6c, 0x5d, 0x03, + 0x48, 0x8a, 0x38, 0xed, 0x52, 0x03, 0xaa, 0x68, + + 0xed, 0x53, 0x03, 0xcd, 0x4e, 0x03, 0x60, 0xa9, + 0x0f, 0x8d, 0x67, 0x03, 0xa9, 0x0c, 0xa0, 0x06, + + 0x99, 0x68, 0x03, 0x88, 0x10, 0xfa, 0xe0, 0x07, + 0x90, 0x02, 0xa2, 0x06, 0x8e, 0x46, 0x02, 0xad, + + 0x43, 0x02, 0xa2, 0x00, 0xec, 0x46, 0x02, 0xb0, + 0x0b, 0xbc, 0xba, 0xc4, 0x99, 0x68, 0x03, 0x69, + + 0x01, 0xe8, 0xd0, 0xf0, 0x8d, 0x44, 0x02, 0xa8, + 0xf0, 0xcc, 0xa2, 0x11, 0x4c, 0x68, 0xf1, 0xa9, + + 0x02, 0x24, 0xd0, 0xd0, 0x02, 0x50, 0x32, 0xad, + 0x09, 0x03, 0x90, 0x03, 0xad, 0x0b, 0x03, 0x70, + + 0x08, 0x8d, 0x19, 0x03, 0x68, 0x68, 0x4c, 0xaf, + 0xc6, 0x08, 0xcd, 0x65, 0x03, 0xf0, 0x19, 0x28, + + 0x90, 0x04, 0xce, 0x65, 0x03, 0x60, 0xee, 0x65, + 0x03, 0x60, 0x08, 0x48, 0xac, 0x4f, 0x03, 0x88, + + 0xd0, 0x1d, 0xad, 0x38, 0x03, 0x91, 0xd8, 0x68, + 0x28, 0x60, 0x08, 0x48, 0xac, 0x4f, 0x03, 0x88, + + 0xd0, 0x0d, 0xb1, 0xd8, 0x8d, 0x38, 0x03, 0xad, + 0x66, 0x03, 0x91, 0xd8, 0x4c, 0x77, 0xcd, 0xa9, + + 0xff, 0xc0, 0x1f, 0xd0, 0x02, 0xa9, 0x3f, 0x85, + 0xda, 0xb1, 0xd8, 0x45, 0xda, 0x91, 0xd8, 0x88, + + 0x10, 0xf7, 0x30, 0xd3, 0x20, 0x5b, 0xce, 0xad, + 0x09, 0x03, 0x8d, 0x19, 0x03, 0x20, 0x06, 0xcf, + + 0x20, 0xf8, 0xcc, 0xb0, 0x03, 0x6d, 0x54, 0x03, + 0x85, 0xdb, 0x86, 0xda, 0x85, 0xdc, 0xb0, 0x06, + + 0x20, 0x73, 0xce, 0x4c, 0xce, 0xcd, 0x20, 0xf8, + 0xcc, 0x90, 0xf5, 0x20, 0x38, 0xce, 0xa5, 0xdc, + + 0xa6, 0xda, 0x85, 0xd9, 0x86, 0xd8, 0xc6, 0xde, + 0xd0, 0xd6, 0xa2, 0x28, 0xa0, 0x18, 0xa9, 0x02, + + 0xd0, 0x06, 0xa2, 0x24, 0xa0, 0x14, 0xa9, 0x04, + 0x85, 0xda, 0xbd, 0x00, 0x03, 0x48, 0xb9, 0x00, + + 0x03, 0x9d, 0x00, 0x03, 0x68, 0x99, 0x00, 0x03, + 0xe8, 0xc8, 0xc6, 0xda, 0xd0, 0xec, 0x60, 0x20, + + 0x5b, 0xce, 0xac, 0x0b, 0x03, 0x8c, 0x19, 0x03, + 0x20, 0x06, 0xcf, 0x20, 0xd4, 0xca, 0x10, 0x04, + + 0x38, 0xed, 0x54, 0x03, 0x85, 0xdb, 0x86, 0xda, + 0x85, 0xdc, 0x90, 0x06, 0x20, 0x73, 0xce, 0x4c, + + 0x2a, 0xce, 0x20, 0xd4, 0xca, 0x30, 0xf5, 0x20, + 0x38, 0xce, 0xa5, 0xdc, 0xa6, 0xda, 0x85, 0xd9, + + 0x86, 0xd8, 0xc6, 0xde, 0xd0, 0xd5, 0xf0, 0xa2, + 0xae, 0x4d, 0x03, 0xf0, 0x10, 0xa0, 0x00, 0xb1, + + 0xda, 0x91, 0xd8, 0xc8, 0xd0, 0xf9, 0xe6, 0xd9, + 0xe6, 0xdb, 0xca, 0xd0, 0xf2, 0xac, 0x4c, 0x03, + + 0xf0, 0x08, 0x88, 0xb1, 0xda, 0x91, 0xd8, 0x98, + 0xd0, 0xf8, 0x60, 0x20, 0xda, 0xcd, 0x38, 0xad, + + 0x09, 0x03, 0xed, 0x0b, 0x03, 0x85, 0xde, 0xd0, + 0x05, 0x68, 0x68, 0x4c, 0xda, 0xcd, 0xad, 0x08, + + 0x03, 0x10, 0x70, 0xa5, 0xda, 0x48, 0x38, 0xad, + 0x0a, 0x03, 0xed, 0x08, 0x03, 0x85, 0xdf, 0xac, + + 0x4f, 0x03, 0x88, 0xb1, 0xda, 0x91, 0xd8, 0x88, + 0x10, 0xf9, 0xa2, 0x02, 0x18, 0xb5, 0xd8, 0x6d, + + 0x4f, 0x03, 0x95, 0xd8, 0xb5, 0xd9, 0x69, 0x00, + 0x10, 0x04, 0x38, 0xed, 0x54, 0x03, 0x95, 0xd9, + + 0xca, 0xca, 0xf0, 0xe8, 0xc6, 0xdf, 0x10, 0xd7, + 0x68, 0x85, 0xda, 0x60, 0xad, 0x18, 0x03, 0x48, + + 0x20, 0x6e, 0xce, 0x20, 0x06, 0xcf, 0x38, 0xad, + 0x0a, 0x03, 0xed, 0x08, 0x03, 0x85, 0xdc, 0xad, + + 0x58, 0x03, 0xac, 0x4f, 0x03, 0x88, 0x91, 0xd8, + 0xd0, 0xfb, 0x8a, 0x18, 0x6d, 0x4f, 0x03, 0xaa, + + 0xa5, 0xd9, 0x69, 0x00, 0x10, 0x04, 0x38, 0xed, + 0x54, 0x03, 0x86, 0xd8, 0x85, 0xd9, 0xc6, 0xdc, + + 0x10, 0xdd, 0x68, 0x8d, 0x18, 0x03, 0x38, 0x60, + 0xae, 0x18, 0x03, 0xec, 0x08, 0x03, 0x30, 0xf6, + + 0xec, 0x0a, 0x03, 0xf0, 0x02, 0x10, 0xef, 0xae, + 0x19, 0x03, 0xec, 0x0b, 0x03, 0x30, 0xe7, 0xec, + + 0x09, 0x03, 0xf0, 0x02, 0x10, 0xe0, 0xad, 0x19, + 0x03, 0x0a, 0xa8, 0xb1, 0xe0, 0x85, 0xd9, 0xc8, + + 0xa9, 0x02, 0x2d, 0x56, 0x03, 0x08, 0xb1, 0xe0, + 0x28, 0xf0, 0x03, 0x46, 0xd9, 0x6a, 0x6d, 0x50, + + 0x03, 0x85, 0xd8, 0xa5, 0xd9, 0x6d, 0x51, 0x03, + 0xa8, 0xad, 0x18, 0x03, 0xae, 0x4f, 0x03, 0xca, + + 0xf0, 0x12, 0xe0, 0x0f, 0xf0, 0x03, 0x90, 0x02, + 0x0a, 0x0a, 0x0a, 0x0a, 0x90, 0x02, 0xc8, 0xc8, + + 0x0a, 0x90, 0x02, 0xc8, 0x18, 0x65, 0xd8, 0x85, + 0xd8, 0x8d, 0x4a, 0x03, 0xaa, 0x98, 0x69, 0x00, + + 0x8d, 0x4b, 0x03, 0x10, 0x04, 0x38, 0xed, 0x54, + 0x03, 0x85, 0xd9, 0x18, 0x60, 0xae, 0x59, 0x03, + + 0xac, 0x5b, 0x03, 0x20, 0xb3, 0xd0, 0x20, 0x86, + 0xd4, 0xa0, 0x00, 0x84, 0xdc, 0xa4, 0xdc, 0xb1, + + 0xde, 0xf0, 0x13, 0x85, 0xdd, 0x10, 0x03, 0x20, + 0xe3, 0xd0, 0xee, 0x24, 0x03, 0xd0, 0x03, 0xee, + + 0x25, 0x03, 0x06, 0xdd, 0xd0, 0xef, 0xa2, 0x28, + 0xa0, 0x24, 0x20, 0x82, 0xd4, 0xac, 0x26, 0x03, + + 0xd0, 0x03, 0xce, 0x27, 0x03, 0xce, 0x26, 0x03, + 0xa4, 0xdc, 0xc8, 0xc0, 0x08, 0xd0, 0xcc, 0xa2, + + 0x28, 0xa0, 0x24, 0x4c, 0x8a, 0xd4, 0xa2, 0x06, + 0xa0, 0x26, 0x20, 0x82, 0xd4, 0xa2, 0x00, 0xa0, + + 0x24, 0x20, 0x82, 0xd4, 0x4c, 0xb8, 0xd1, 0xae, + 0x60, 0x03, 0xf0, 0x20, 0x20, 0x3e, 0xd0, 0xae, + + 0x60, 0x03, 0xa5, 0xd0, 0x29, 0x20, 0xd0, 0x95, + 0xa0, 0x07, 0xe0, 0x03, 0xf0, 0x20, 0xb0, 0x4e, + + 0xb1, 0xde, 0x05, 0xd2, 0x45, 0xd3, 0x91, 0xd8, + 0x88, 0x10, 0xf5, 0x60, 0xa0, 0x02, 0xd9, 0xb6, + + 0xc4, 0xf0, 0x06, 0x88, 0x10, 0xf8, 0x81, 0xd8, + 0x60, 0xb9, 0xb7, 0xc4, 0xd0, 0xf8, 0xb1, 0xde, + + 0x48, 0x4a, 0x4a, 0x4a, 0x4a, 0xaa, 0xbd, 0x1f, + 0xc3, 0x05, 0xd2, 0x45, 0xd3, 0x91, 0xd8, 0x98, + + 0x18, 0x69, 0x08, 0xa8, 0x68, 0x29, 0x0f, 0xaa, + 0xbd, 0x1f, 0xc3, 0x05, 0xd2, 0x45, 0xd3, 0x91, + + 0xd8, 0x98, 0xe9, 0x08, 0xa8, 0x10, 0xd7, 0x60, + 0x98, 0xe9, 0x21, 0x30, 0xfa, 0xa8, 0xb1, 0xde, + + 0x85, 0xdc, 0x38, 0xa9, 0x00, 0x26, 0xdc, 0xf0, + 0xef, 0x2a, 0x06, 0xdc, 0x2a, 0xaa, 0xbd, 0x2f, + + 0xc3, 0x05, 0xd2, 0x45, 0xd3, 0x91, 0xd8, 0x18, + 0x98, 0x69, 0x08, 0xa8, 0x90, 0xe5, 0x0a, 0x2a, + + 0x2a, 0x85, 0xde, 0x29, 0x03, 0x2a, 0xaa, 0x29, + 0x03, 0x69, 0xbf, 0xa8, 0xbd, 0x0d, 0xc4, 0x2c, + + 0x67, 0x03, 0xf0, 0x03, 0xbc, 0x67, 0x03, 0x84, + 0xdf, 0xa5, 0xde, 0x29, 0xf8, 0x85, 0xde, 0x60, + + 0xa2, 0x20, 0x20, 0x4d, 0xd1, 0xad, 0x1f, 0x03, + 0xc9, 0x04, 0xf0, 0x6d, 0xa0, 0x05, 0x29, 0x03, + + 0xf0, 0x0e, 0x4a, 0xb0, 0x03, 0x88, 0xd0, 0x08, + 0xaa, 0xbc, 0x5b, 0x03, 0xbd, 0x59, 0x03, 0xaa, + + 0x20, 0xb3, 0xd0, 0xad, 0x1f, 0x03, 0x30, 0x23, + 0x0a, 0x10, 0x3b, 0x29, 0xf0, 0x0a, 0xf0, 0x46, + + 0x49, 0x40, 0xf0, 0x14, 0x48, 0x20, 0xdc, 0xd0, + 0x68, 0x49, 0x60, 0xf0, 0x11, 0xc9, 0x40, 0xd0, + + 0x0a, 0xa9, 0x02, 0x85, 0xdc, 0x4c, 0x06, 0xd5, + 0x4c, 0xea, 0xd5, 0x4c, 0x38, 0xc9, 0x85, 0xdc, + + 0x4c, 0xbf, 0xd4, 0x8a, 0x19, 0x1c, 0xc4, 0x59, + 0x1d, 0xc4, 0x85, 0xd4, 0x8a, 0x19, 0x1b, 0xc4, + + 0x59, 0x20, 0xc4, 0x85, 0xd5, 0x60, 0x0a, 0x30, + 0xe2, 0x0a, 0x0a, 0x10, 0x03, 0x20, 0xeb, 0xd0, + + 0x20, 0xed, 0xd1, 0x4c, 0xd9, 0xd0, 0x20, 0xeb, + 0xd0, 0x20, 0xe2, 0xcd, 0xa0, 0x24, 0xa2, 0x20, + + 0x4c, 0x8a, 0xd4, 0xa2, 0x24, 0x20, 0x5f, 0xd8, + 0xf0, 0x06, 0x60, 0x20, 0x5d, 0xd8, 0xd0, 0x13, + + 0xac, 0x1a, 0x03, 0xa5, 0xd1, 0x25, 0xd4, 0x11, + 0xd6, 0x85, 0xda, 0xa5, 0xd5, 0x25, 0xd1, 0x45, + + 0xda, 0x91, 0xd6, 0x60, 0xb1, 0xd6, 0x05, 0xd4, + 0x45, 0xd5, 0x91, 0xd6, 0x60, 0xa2, 0x24, 0xa0, + + 0x00, 0x84, 0xda, 0xa0, 0x02, 0x20, 0x28, 0xd1, + 0x06, 0xda, 0x06, 0xda, 0xca, 0xca, 0xa0, 0x00, + + 0x20, 0x28, 0xd1, 0xe8, 0xe8, 0xa5, 0xda, 0x60, + 0xbd, 0x02, 0x03, 0xd9, 0x00, 0x03, 0xbd, 0x03, + + 0x03, 0xf9, 0x01, 0x03, 0x30, 0x10, 0xb9, 0x04, + 0x03, 0xdd, 0x02, 0x03, 0xb9, 0x05, 0x03, 0xfd, + + 0x03, 0x03, 0x10, 0x04, 0xe6, 0xda, 0xe6, 0xda, + 0x60, 0xa9, 0xff, 0xd0, 0x03, 0xad, 0x1f, 0x03, + + 0x85, 0xda, 0xa0, 0x02, 0x20, 0x76, 0xd1, 0x20, + 0xad, 0xd1, 0xa0, 0x00, 0xca, 0xca, 0x20, 0x76, + + 0xd1, 0xac, 0x61, 0x03, 0xc0, 0x03, 0xf0, 0x05, + 0xb0, 0x06, 0x20, 0xad, 0xd1, 0x20, 0xad, 0xd1, + + 0xad, 0x56, 0x03, 0xd0, 0x38, 0x60, 0x18, 0xa5, + 0xda, 0x29, 0x04, 0xf0, 0x09, 0xbd, 0x02, 0x03, + + 0x48, 0xbd, 0x03, 0x03, 0x90, 0x0e, 0xbd, 0x02, + 0x03, 0x79, 0x10, 0x03, 0x48, 0xbd, 0x03, 0x03, + + 0x79, 0x11, 0x03, 0x18, 0x99, 0x11, 0x03, 0x79, + 0x0d, 0x03, 0x9d, 0x03, 0x03, 0x68, 0x99, 0x10, + + 0x03, 0x18, 0x79, 0x0c, 0x03, 0x9d, 0x02, 0x03, + 0x90, 0x03, 0xfe, 0x03, 0x03, 0xbd, 0x03, 0x03, + + 0x0a, 0x7e, 0x03, 0x03, 0x7e, 0x02, 0x03, 0x60, + 0xa0, 0x10, 0x20, 0x88, 0xd4, 0xa2, 0x02, 0xa0, + + 0x02, 0x20, 0xd5, 0xd1, 0xa2, 0x00, 0xa0, 0x04, + 0xad, 0x61, 0x03, 0x88, 0x4a, 0xd0, 0xfc, 0xad, + + 0x56, 0x03, 0xf0, 0x01, 0xc8, 0x1e, 0x10, 0x03, + 0x3e, 0x11, 0x03, 0x88, 0xd0, 0xf7, 0x38, 0x20, + + 0xe3, 0xd1, 0xe8, 0xbd, 0x10, 0x03, 0xfd, 0x0c, + 0x03, 0x9d, 0x10, 0x03, 0x60, 0x20, 0x0d, 0xd4, + + 0xad, 0x2b, 0x03, 0x4d, 0x29, 0x03, 0x30, 0x0f, + 0xad, 0x2a, 0x03, 0xcd, 0x28, 0x03, 0xad, 0x2b, + + 0x03, 0xed, 0x29, 0x03, 0x4c, 0x14, 0xd2, 0xad, + 0x28, 0x03, 0x18, 0x6d, 0x2a, 0x03, 0xad, 0x29, + + 0x03, 0x6d, 0x2b, 0x03, 0x6a, 0xa2, 0x00, 0x4d, + 0x2b, 0x03, 0x10, 0x02, 0xa2, 0x02, 0x86, 0xde, + + 0xbd, 0xaa, 0xc4, 0x8d, 0x5d, 0x03, 0xbd, 0xab, + 0xc4, 0x8d, 0x5e, 0x03, 0xbd, 0x29, 0x03, 0x10, + + 0x04, 0xa2, 0x24, 0xd0, 0x02, 0xa2, 0x20, 0x86, + 0xdf, 0xa0, 0x2c, 0x20, 0x8a, 0xd4, 0xa5, 0xdf, + + 0x49, 0x04, 0x85, 0xdd, 0x05, 0xde, 0xaa, 0x20, + 0x80, 0xd4, 0xad, 0x1f, 0x03, 0x29, 0x10, 0x0a, + + 0x0a, 0x0a, 0x85, 0xdb, 0xa2, 0x2c, 0x20, 0x0f, + 0xd1, 0x85, 0xdc, 0xf0, 0x06, 0xa9, 0x40, 0x05, + + 0xdb, 0x85, 0xdb, 0xa6, 0xdd, 0x20, 0x0f, 0xd1, + 0x24, 0xdc, 0xf0, 0x01, 0x60, 0xa6, 0xde, 0xf0, + + 0x02, 0x4a, 0x4a, 0x29, 0x02, 0xf0, 0x07, 0x8a, + 0x09, 0x04, 0xaa, 0x20, 0x80, 0xd4, 0x20, 0x2c, + + 0xd4, 0xa5, 0xde, 0x49, 0x02, 0xaa, 0xa8, 0xad, + 0x29, 0x03, 0x4d, 0x2b, 0x03, 0x10, 0x01, 0xe8, + + 0xbd, 0xae, 0xc4, 0x8d, 0x32, 0x03, 0xbd, 0xb2, + 0xc4, 0x8d, 0x33, 0x03, 0xa9, 0x7f, 0x8d, 0x34, + + 0x03, 0x24, 0xdb, 0x70, 0x29, 0xbd, 0x47, 0xc4, + 0xaa, 0x38, 0xbd, 0x00, 0x03, 0xf9, 0x2c, 0x03, + + 0x85, 0xda, 0xbd, 0x01, 0x03, 0xf9, 0x2d, 0x03, + 0xa4, 0xda, 0xaa, 0x10, 0x03, 0x20, 0x9b, 0xd4, + + 0xaa, 0xc8, 0xd0, 0x01, 0xe8, 0x8a, 0xf0, 0x02, + 0xa0, 0x00, 0x84, 0xdf, 0xf0, 0x09, 0x8a, 0x4a, + + 0x6a, 0x09, 0x02, 0x45, 0xde, 0x85, 0xde, 0xa2, + 0x2c, 0x20, 0x64, 0xd8, 0xa6, 0xdc, 0xd0, 0x02, + + 0xc6, 0xdd, 0xca, 0xa5, 0xdb, 0xf0, 0x1f, 0x10, + 0x10, 0x2c, 0x34, 0x03, 0x10, 0x05, 0xce, 0x34, + + 0x03, 0xd0, 0x23, 0xee, 0x34, 0x03, 0x0a, 0x10, + 0x0d, 0x86, 0xdc, 0xa2, 0x2c, 0x20, 0x5f, 0xd8, + + 0xa6, 0xdc, 0x09, 0x00, 0xd0, 0x10, 0xa5, 0xd1, + 0x25, 0xd4, 0x11, 0xd6, 0x85, 0xda, 0xa5, 0xd5, + + 0x25, 0xd1, 0x45, 0xda, 0x91, 0xd6, 0x38, 0xad, + 0x35, 0x03, 0xed, 0x37, 0x03, 0x8d, 0x35, 0x03, + + 0xad, 0x36, 0x03, 0xed, 0x38, 0x03, 0xb0, 0x11, + 0x85, 0xda, 0xad, 0x35, 0x03, 0x6d, 0x39, 0x03, + + 0x8d, 0x35, 0x03, 0xa5, 0xda, 0x6d, 0x3a, 0x03, + 0x18, 0x8d, 0x36, 0x03, 0x08, 0xb0, 0x09, 0x6c, + + 0x32, 0x03, 0x88, 0x10, 0x03, 0x20, 0xd3, 0xd3, + 0x6c, 0x5d, 0x03, 0xc8, 0xc0, 0x08, 0xd0, 0xf8, + + 0x18, 0xa5, 0xd6, 0x6d, 0x52, 0x03, 0x85, 0xd6, + 0xa5, 0xd7, 0x6d, 0x53, 0x03, 0x10, 0x04, 0x38, + + 0xed, 0x54, 0x03, 0x85, 0xd7, 0xa0, 0x00, 0x6c, + 0x5d, 0x03, 0x46, 0xd1, 0x90, 0xda, 0x20, 0xed, + + 0xd3, 0x6c, 0x5d, 0x03, 0x06, 0xd1, 0x90, 0xd0, + 0x20, 0xfd, 0xd3, 0x6c, 0x5d, 0x03, 0x88, 0x10, + + 0x0c, 0x20, 0xd3, 0xd3, 0xd0, 0x07, 0x46, 0xd1, + 0x90, 0x03, 0x20, 0xed, 0xd3, 0x28, 0xe8, 0xd0, + + 0x04, 0xe6, 0xdd, 0xf0, 0x0a, 0x24, 0xdb, 0x70, + 0x07, 0xb0, 0x35, 0xc6, 0xdf, 0xd0, 0x31, 0x60, + + 0xa5, 0xde, 0x86, 0xdc, 0x29, 0x02, 0xaa, 0xb0, + 0x19, 0x24, 0xde, 0x30, 0x0a, 0xfe, 0x2c, 0x03, + + 0xd0, 0x10, 0xfe, 0x2d, 0x03, 0x90, 0x0b, 0xbd, + 0x2c, 0x03, 0xd0, 0x03, 0xde, 0x2d, 0x03, 0xde, + + 0x2c, 0x03, 0x8a, 0x49, 0x02, 0xaa, 0xfe, 0x2c, + 0x03, 0xd0, 0x03, 0xfe, 0x2d, 0x03, 0xa6, 0xdc, + + 0x4c, 0xe3, 0xd2, 0x38, 0xa5, 0xd6, 0xed, 0x52, + 0x03, 0x85, 0xd6, 0xa5, 0xd7, 0xed, 0x53, 0x03, + + 0xcd, 0x4e, 0x03, 0xb0, 0x03, 0x6d, 0x54, 0x03, + 0x85, 0xd7, 0xa0, 0x07, 0x60, 0xad, 0x62, 0x03, + + 0x85, 0xd1, 0xa5, 0xd6, 0x69, 0x07, 0x85, 0xd6, + 0x90, 0x02, 0xe6, 0xd7, 0x60, 0xad, 0x63, 0x03, + + 0x85, 0xd1, 0xa5, 0xd6, 0xd0, 0x02, 0xc6, 0xd7, + 0xe9, 0x08, 0x85, 0xd6, 0x60, 0xa0, 0x28, 0xa2, + + 0x20, 0x20, 0x18, 0xd4, 0xe8, 0xe8, 0xc8, 0xc8, + 0x38, 0xbd, 0x04, 0x03, 0xfd, 0x00, 0x03, 0x99, + + 0x00, 0x03, 0xbd, 0x05, 0x03, 0xfd, 0x01, 0x03, + 0x99, 0x01, 0x03, 0x60, 0xa5, 0xde, 0xd0, 0x07, + + 0xa2, 0x28, 0xa0, 0x2a, 0x20, 0xde, 0xcd, 0xa2, + 0x28, 0xa0, 0x37, 0x20, 0x8a, 0xd4, 0x38, 0xa6, + + 0xde, 0xad, 0x30, 0x03, 0xfd, 0x2c, 0x03, 0xa8, + 0xad, 0x31, 0x03, 0xfd, 0x2d, 0x03, 0x30, 0x03, + + 0x20, 0x9b, 0xd4, 0x85, 0xdd, 0x84, 0xdc, 0xa2, + 0x35, 0x20, 0x67, 0xd4, 0x4a, 0x9d, 0x01, 0x03, + + 0x98, 0x6a, 0x9d, 0x00, 0x03, 0xca, 0xca, 0xbc, + 0x04, 0x03, 0xbd, 0x05, 0x03, 0x10, 0x0c, 0x20, + + 0x9b, 0xd4, 0x9d, 0x05, 0x03, 0x48, 0x98, 0x9d, + 0x04, 0x03, 0x68, 0x60, 0xa9, 0x08, 0xd0, 0x0c, + + 0xa0, 0x30, 0xa9, 0x02, 0xd0, 0x06, 0xa0, 0x28, + 0xa2, 0x24, 0xa9, 0x04, 0x85, 0xda, 0xbd, 0x00, + + 0x03, 0x99, 0x00, 0x03, 0xe8, 0xc8, 0xc6, 0xda, + 0xd0, 0xf4, 0x60, 0x48, 0x98, 0x49, 0xff, 0xa8, + + 0x68, 0x49, 0xff, 0xc8, 0xd0, 0x03, 0x18, 0x69, + 0x01, 0x60, 0x20, 0x5d, 0xd8, 0xd0, 0x08, 0xb1, + + 0xd6, 0x4d, 0x5a, 0x03, 0x85, 0xda, 0x60, 0x68, + 0x68, 0xee, 0x26, 0x03, 0x4c, 0x45, 0xd5, 0x20, + + 0xaa, 0xd4, 0x25, 0xd1, 0xd0, 0xf3, 0xa2, 0x00, + 0x20, 0x92, 0xd5, 0xf0, 0x2d, 0xac, 0x1a, 0x03, + + 0x06, 0xd1, 0xb0, 0x05, 0x20, 0x74, 0xd5, 0x90, + 0x21, 0x20, 0xfd, 0xd3, 0xb1, 0xd6, 0x4d, 0x5a, + + 0x03, 0x85, 0xda, 0xd0, 0x12, 0x38, 0x8a, 0x6d, + 0x61, 0x03, 0x90, 0x04, 0xe6, 0xdb, 0x10, 0x07, + + 0xaa, 0x20, 0x04, 0xd1, 0x38, 0xb0, 0xe2, 0x20, + 0x74, 0xd5, 0xa0, 0x00, 0x20, 0xac, 0xd5, 0xa0, + + 0x20, 0xa2, 0x24, 0x20, 0xe6, 0xcd, 0x20, 0xaa, + 0xd4, 0xa2, 0x04, 0x20, 0x92, 0xd5, 0x8a, 0xd0, + + 0x02, 0xc6, 0xdb, 0xca, 0x20, 0x4b, 0xd5, 0x90, + 0x27, 0x20, 0xed, 0xd3, 0xb1, 0xd6, 0x4d, 0x5a, + + 0x03, 0x85, 0xda, 0xa5, 0xdc, 0xd0, 0xed, 0xa5, + 0xda, 0xd0, 0x12, 0x38, 0x8a, 0x6d, 0x61, 0x03, + + 0x90, 0x04, 0xe6, 0xdb, 0x10, 0x07, 0xaa, 0x20, + 0x04, 0xd1, 0x38, 0xb0, 0xdc, 0x20, 0x4b, 0xd5, + + 0xa0, 0x04, 0x20, 0xac, 0xd5, 0x20, 0xd9, 0xd0, + 0x4c, 0xb8, 0xd1, 0xa5, 0xd1, 0x48, 0x18, 0x90, + + 0x0f, 0x68, 0xe8, 0xd0, 0x04, 0xe6, 0xdb, 0x10, + 0x16, 0x46, 0xd1, 0xb0, 0x12, 0x05, 0xd1, 0x48, + + 0xa5, 0xd1, 0x24, 0xda, 0x08, 0x68, 0x45, 0xdc, + 0x48, 0x28, 0xf0, 0xe5, 0x68, 0x45, 0xd1, 0x85, + + 0xd1, 0x4c, 0xf0, 0xd0, 0xa9, 0x00, 0x18, 0x90, + 0x0a, 0xe8, 0xd0, 0x04, 0xe6, 0xdb, 0x10, 0xef, + + 0x0a, 0xb0, 0x0b, 0x05, 0xd1, 0x24, 0xda, 0xf0, + 0xf0, 0x45, 0xd1, 0x4a, 0x90, 0xe1, 0x6a, 0x38, + + 0xb0, 0xdd, 0xbd, 0x00, 0x03, 0x38, 0xed, 0x20, + 0x03, 0xa8, 0xbd, 0x01, 0x03, 0xed, 0x21, 0x03, + + 0x30, 0x03, 0x20, 0x9b, 0xd4, 0x85, 0xdb, 0x98, + 0xaa, 0x05, 0xdb, 0x60, 0x84, 0xda, 0x8a, 0xa8, + + 0xa5, 0xdb, 0x30, 0x02, 0xa9, 0x00, 0xa6, 0xda, + 0xd0, 0x03, 0x20, 0x9b, 0xd4, 0x48, 0x18, 0x98, + + 0x7d, 0x00, 0x03, 0x8d, 0x20, 0x03, 0x68, 0x7d, + 0x01, 0x03, 0x8d, 0x21, 0x03, 0x60, 0xa9, 0x03, + + 0x20, 0xd5, 0xd5, 0xa9, 0x07, 0x48, 0x20, 0xe2, + 0xcd, 0x20, 0xb8, 0xd1, 0xa2, 0x03, 0x68, 0xa8, + + 0xbd, 0x10, 0x03, 0x91, 0xf0, 0x88, 0xca, 0x10, + 0xf7, 0x60, 0xa2, 0x20, 0xa0, 0x3e, 0x20, 0x7c, + + 0xd4, 0x20, 0x32, 0xd6, 0xa2, 0x14, 0xa0, 0x24, + 0x20, 0x36, 0xd6, 0x20, 0x32, 0xd6, 0xa2, 0x20, + + 0xa0, 0x2a, 0x20, 0x11, 0xd4, 0xad, 0x2b, 0x03, + 0x8d, 0x32, 0x03, 0xa2, 0x28, 0x20, 0x59, 0xd4, + + 0xa0, 0x2e, 0x20, 0xde, 0xd0, 0x20, 0xe2, 0xcd, + 0x18, 0x20, 0x58, 0xd6, 0x20, 0xe2, 0xcd, 0xa2, + + 0x20, 0x20, 0xe4, 0xcd, 0x38, 0x20, 0x58, 0xd6, + 0xa2, 0x3e, 0xa0, 0x20, 0x20, 0x7c, 0xd4, 0x4c, + + 0xd9, 0xd0, 0xa2, 0x20, 0xa0, 0x14, 0xbd, 0x02, + 0x03, 0xd9, 0x02, 0x03, 0xbd, 0x03, 0x03, 0xf9, + + 0x03, 0x03, 0x30, 0x13, 0x4c, 0xe6, 0xcd, 0xad, + 0x18, 0x03, 0x38, 0xed, 0x08, 0x03, 0xaa, 0xad, + + 0x19, 0x03, 0x38, 0xed, 0x0b, 0x03, 0xa8, 0x60, + 0x08, 0xa2, 0x20, 0xa0, 0x35, 0x20, 0x11, 0xd4, + + 0xad, 0x36, 0x03, 0x8d, 0x3d, 0x03, 0xa2, 0x33, + 0x20, 0x59, 0xd4, 0xa0, 0x39, 0x20, 0xde, 0xd0, + + 0x38, 0xad, 0x22, 0x03, 0xed, 0x26, 0x03, 0x8d, + 0x1b, 0x03, 0xad, 0x23, 0x03, 0xed, 0x27, 0x03, + + 0x8d, 0x1c, 0x03, 0x0d, 0x1b, 0x03, 0xf0, 0x17, + 0x20, 0xa2, 0xd6, 0xa2, 0x33, 0x20, 0x74, 0xd7, + + 0xa2, 0x28, 0x20, 0x74, 0xd7, 0xee, 0x1b, 0x03, + 0xd0, 0xee, 0xee, 0x1c, 0x03, 0xd0, 0xe9, 0x28, + + 0x90, 0xb5, 0xa2, 0x39, 0xa0, 0x2e, 0x86, 0xde, + 0xbd, 0x00, 0x03, 0xd9, 0x00, 0x03, 0xbd, 0x01, + + 0x03, 0xf9, 0x01, 0x03, 0x30, 0x06, 0x98, 0xa4, + 0xde, 0xaa, 0x86, 0xde, 0x84, 0xdf, 0xb9, 0x00, + + 0x03, 0x48, 0xb9, 0x01, 0x03, 0x48, 0xa6, 0xdf, + 0x20, 0x0f, 0xd1, 0xf0, 0x0d, 0xc9, 0x02, 0xd0, + + 0x3d, 0xa2, 0x04, 0xa4, 0xdf, 0x20, 0x82, 0xd4, + 0xa6, 0xdf, 0x20, 0x64, 0xd8, 0xa6, 0xde, 0x20, + + 0x0f, 0xd1, 0x4a, 0xd0, 0x29, 0x90, 0x02, 0xa2, + 0x00, 0xa4, 0xdf, 0x38, 0xb9, 0x00, 0x03, 0xfd, + + 0x00, 0x03, 0x85, 0xdc, 0xb9, 0x01, 0x03, 0xfd, + 0x01, 0x03, 0x85, 0xdd, 0xa9, 0x00, 0x0a, 0x05, + + 0xd1, 0xa4, 0xdc, 0xd0, 0x14, 0xc6, 0xdd, 0x10, + 0x10, 0x85, 0xd1, 0x20, 0xf0, 0xd0, 0xa6, 0xdf, + + 0x68, 0x9d, 0x01, 0x03, 0x68, 0x9d, 0x00, 0x03, + 0x60, 0xc6, 0xdc, 0xaa, 0x10, 0xe0, 0x85, 0xd1, + + 0x20, 0xf0, 0xd0, 0xa6, 0xdc, 0xe8, 0xd0, 0x02, + 0xe6, 0xdd, 0x8a, 0x48, 0x46, 0xdd, 0x6a, 0xac, + + 0x61, 0x03, 0xc0, 0x03, 0xf0, 0x05, 0x90, 0x06, + 0x46, 0xdd, 0x6a, 0x46, 0xdd, 0x4a, 0xac, 0x1a, + + 0x03, 0xaa, 0xf0, 0x0f, 0x98, 0x38, 0xe9, 0x08, + 0xa8, 0xb0, 0x02, 0xc6, 0xd7, 0x20, 0x04, 0xd1, + + 0xca, 0xd0, 0xf1, 0x68, 0x2d, 0x61, 0x03, 0xf0, + 0xb5, 0xaa, 0xa9, 0x00, 0x0a, 0x0d, 0x63, 0x03, + + 0xca, 0xd0, 0xf9, 0x85, 0xd1, 0x98, 0x38, 0xe9, + 0x08, 0xa8, 0xb0, 0x02, 0xc6, 0xd7, 0x20, 0xf3, + + 0xd0, 0x4c, 0x0e, 0xd7, 0xfe, 0x08, 0x03, 0xd0, + 0x03, 0xfe, 0x09, 0x03, 0x38, 0xbd, 0x00, 0x03, + + 0xfd, 0x02, 0x03, 0x9d, 0x00, 0x03, 0xbd, 0x01, + 0x03, 0xfd, 0x03, 0x03, 0x9d, 0x01, 0x03, 0x10, + + 0x30, 0xbd, 0x0a, 0x03, 0x30, 0x0b, 0xfe, 0x06, + 0x03, 0xd0, 0x11, 0xfe, 0x07, 0x03, 0x4c, 0xac, + + 0xd7, 0xbd, 0x06, 0x03, 0xd0, 0x03, 0xde, 0x07, + 0x03, 0xde, 0x06, 0x03, 0x18, 0xbd, 0x00, 0x03, + + 0x7d, 0x04, 0x03, 0x9d, 0x00, 0x03, 0xbd, 0x01, + 0x03, 0x7d, 0x05, 0x03, 0x9d, 0x01, 0x03, 0x30, + + 0xd0, 0x60, 0xac, 0x60, 0x03, 0xd0, 0x15, 0xb1, + 0xd8, 0xa0, 0x02, 0xd9, 0xb7, 0xc4, 0xd0, 0x04, + + 0xb9, 0xb6, 0xc4, 0x88, 0x88, 0x10, 0xf4, 0xac, + 0x55, 0x03, 0xaa, 0x60, 0x20, 0x08, 0xd8, 0xa2, + + 0x20, 0x8a, 0x48, 0x20, 0x3e, 0xd0, 0x68, 0xaa, + 0xa0, 0x07, 0xb9, 0x28, 0x03, 0xd1, 0xde, 0xd0, + + 0x08, 0x88, 0x10, 0xf6, 0x8a, 0xe0, 0x7f, 0xd0, + 0xde, 0xe8, 0xa5, 0xde, 0x18, 0x69, 0x08, 0x85, + + 0xde, 0xd0, 0xe5, 0x8a, 0xd0, 0xdb, 0xf0, 0xcf, + 0xa0, 0x07, 0x84, 0xda, 0xa9, 0x01, 0x85, 0xdb, + + 0xad, 0x62, 0x03, 0x85, 0xdc, 0xb1, 0xd8, 0x4d, + 0x58, 0x03, 0x18, 0x24, 0xdc, 0xf0, 0x01, 0x38, + + 0x26, 0xdb, 0xb0, 0x0a, 0x46, 0xdc, 0x90, 0xf3, + 0x98, 0x69, 0x07, 0xa8, 0x90, 0xe2, 0xa4, 0xda, + + 0xa5, 0xdb, 0x99, 0x28, 0x03, 0x88, 0x10, 0xd2, + 0x60, 0x48, 0xaa, 0x20, 0x49, 0xd1, 0x68, 0xaa, + + 0x20, 0x5f, 0xd8, 0xd0, 0x15, 0xb1, 0xd6, 0x0a, + 0x26, 0xda, 0x06, 0xd1, 0x08, 0xb0, 0x02, 0x46, + + 0xda, 0x28, 0xd0, 0xf3, 0xa5, 0xda, 0x2d, 0x60, + 0x03, 0x60, 0xa9, 0xff, 0x60, 0xa2, 0x20, 0x20, + + 0x0f, 0xd1, 0xd0, 0xf8, 0xbd, 0x02, 0x03, 0x49, + 0xff, 0xa8, 0x29, 0x07, 0x8d, 0x1a, 0x03, 0x98, + + 0x4a, 0x4a, 0x4a, 0x0a, 0xa8, 0xb1, 0xe0, 0x85, + 0xda, 0xc8, 0xb1, 0xe0, 0xac, 0x56, 0x03, 0xf0, + + 0x03, 0x46, 0xda, 0x6a, 0x6d, 0x50, 0x03, 0x85, + 0xd6, 0xa5, 0xda, 0x6d, 0x51, 0x03, 0x85, 0xd7, + + 0xbd, 0x01, 0x03, 0x85, 0xda, 0xbd, 0x00, 0x03, + 0x48, 0x2d, 0x61, 0x03, 0x6d, 0x61, 0x03, 0xa8, + + 0xb9, 0x06, 0xc4, 0x85, 0xd1, 0x68, 0xac, 0x61, + 0x03, 0xc0, 0x03, 0xf0, 0x05, 0xb0, 0x06, 0x0a, + + 0x26, 0xda, 0x0a, 0x26, 0xda, 0x29, 0xf8, 0x18, + 0x65, 0xd6, 0x85, 0xd6, 0xa5, 0xda, 0x65, 0xd7, + + 0x10, 0x04, 0x38, 0xed, 0x54, 0x03, 0x85, 0xd7, + 0xac, 0x1a, 0x03, 0xa9, 0x00, 0x60, 0x48, 0xa9, + + 0xa0, 0xae, 0x6a, 0x02, 0xd0, 0x40, 0x24, 0xd0, + 0xd0, 0x3c, 0x70, 0x19, 0xad, 0x5f, 0x03, 0x29, + + 0x9f, 0x09, 0x40, 0x20, 0x54, 0xc9, 0xa2, 0x18, + 0xa0, 0x64, 0x20, 0x82, 0xd4, 0x20, 0x7a, 0xcd, + + 0xa9, 0x02, 0x20, 0x9d, 0xc5, 0xa9, 0xbf, 0x20, + 0xa8, 0xc5, 0x68, 0x29, 0x7f, 0x20, 0xc0, 0xc4, + + 0xa9, 0x40, 0x4c, 0x9d, 0xc5, 0xa9, 0x20, 0x24, + 0xd0, 0x50, 0xc0, 0xd0, 0xbe, 0x20, 0xc2, 0xd7, + + 0xf0, 0x05, 0x48, 0x20, 0x64, 0xc6, 0x68, 0x60, + 0xa9, 0xbd, 0x20, 0xa8, 0xc5, 0x20, 0x51, 0xc9, + + 0xa9, 0x0d, 0x60, 0xae, 0x55, 0x03, 0x8a, 0x29, + 0x07, 0xa8, 0xbe, 0x40, 0xc4, 0xbd, 0x5e, 0xc4, + + 0xa2, 0x00, 0x2c, 0x8e, 0x02, 0x30, 0x07, 0x29, + 0x3f, 0xc0, 0x04, 0xb0, 0x01, 0x8a, 0xa8, 0x60, + + 0x10, 0xe3, 0x54, 0xdc, 0x93, 0xdc, 0x89, 0xde, + 0x89, 0xdf, 0x72, 0xe7, 0xeb, 0xe7, 0xa4, 0xe0, + + 0xc5, 0xde, 0x7d, 0xf2, 0x8e, 0xf1, 0xc9, 0xf4, + 0x29, 0xf5, 0xa6, 0xff, 0xca, 0xf3, 0xb1, 0xf1, + + 0xa6, 0xff, 0xa6, 0xff, 0xa6, 0xff, 0xa6, 0xff, + 0x02, 0xef, 0xb3, 0xe4, 0x64, 0xe4, 0xd1, 0xe1, + + 0xa6, 0xff, 0xa6, 0xff, 0xa6, 0xff, 0x90, 0x01, + 0x9f, 0x0d, 0xa1, 0x02, 0x2b, 0xf0, 0x00, 0x03, + + 0x00, 0x00, 0xff, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0x04, 0x04, 0x00, 0xff, + + 0x56, 0x19, 0x19, 0x19, 0x32, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x20, 0x09, 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x50, 0x00, 0x03, 0x90, 0x64, 0x06, 0x81, + 0x00, 0x00, 0x00, 0x09, 0x1b, 0x01, 0xd0, 0xe0, + + 0xf0, 0x01, 0x80, 0x90, 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x64, 0x05, 0xff, 0x01, 0x0a, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xa9, 0x40, 0x8d, + + 0x00, 0x0d, 0x78, 0xd8, 0xa2, 0xff, 0x9a, 0xad, + 0x4e, 0xfe, 0x0a, 0x48, 0xf0, 0x09, 0xad, 0x58, + + 0x02, 0x4a, 0xc9, 0x01, 0xd0, 0x1d, 0x4a, 0xa2, + 0x04, 0x86, 0x01, 0x85, 0x00, 0xa8, 0x91, 0x00, + + 0xc5, 0x01, 0xf0, 0x09, 0xc8, 0xd0, 0xf7, 0xc8, + 0xe8, 0xe6, 0x01, 0x10, 0xf1, 0x8e, 0x8e, 0x02, + + 0x8e, 0x84, 0x02, 0xa2, 0x0f, 0x8e, 0x42, 0xfe, + 0xca, 0x8e, 0x40, 0xfe, 0xe0, 0x09, 0xb0, 0xf8, + + 0xe8, 0x8a, 0x20, 0x2a, 0xf0, 0xe0, 0x80, 0x66, + 0xfc, 0xaa, 0xca, 0xd0, 0xf4, 0x8e, 0x8d, 0x02, + + 0x26, 0xfc, 0x20, 0xeb, 0xee, 0x6a, 0xa2, 0x9c, + 0xa0, 0x8d, 0x68, 0xf0, 0x09, 0xa0, 0x7e, 0x90, + + 0x11, 0xa0, 0x87, 0xee, 0x8d, 0x02, 0xee, 0x8d, + 0x02, 0xa5, 0xfc, 0x49, 0xff, 0x8d, 0x8f, 0x02, + + 0xa2, 0x90, 0xa9, 0x00, 0xe0, 0xce, 0x90, 0x02, + 0xa9, 0xff, 0x9d, 0x00, 0x02, 0xe8, 0xd0, 0xf4, + + 0x8d, 0x63, 0xfe, 0x8a, 0xa2, 0xe2, 0x95, 0x00, + 0xe8, 0xd0, 0xfb, 0xb9, 0x3f, 0xd9, 0x99, 0xff, + + 0x01, 0x88, 0xd0, 0xf7, 0xa9, 0x62, 0x85, 0xed, + 0x20, 0x0a, 0xfb, 0xa9, 0x7f, 0xe8, 0x9d, 0x4d, + + 0xfe, 0x9d, 0x6d, 0xfe, 0xca, 0x10, 0xf7, 0x58, + 0x78, 0x24, 0xfc, 0x50, 0x03, 0x20, 0x55, 0xf0, + + 0xa2, 0xf2, 0x8e, 0x4e, 0xfe, 0xa2, 0x04, 0x8e, + 0x4c, 0xfe, 0xa9, 0x60, 0x8d, 0x4b, 0xfe, 0xa9, + + 0x0e, 0x8d, 0x46, 0xfe, 0x8d, 0x6c, 0xfe, 0x8d, + 0xc0, 0xfe, 0xcd, 0x6c, 0xfe, 0xf0, 0x03, 0xee, + + 0x77, 0x02, 0xa9, 0x27, 0x8d, 0x47, 0xfe, 0x8d, + 0x45, 0xfe, 0x20, 0x60, 0xec, 0xad, 0x82, 0x02, + + 0x29, 0x7f, 0x20, 0xa7, 0xe6, 0xae, 0x84, 0x02, + 0xf0, 0x03, 0x20, 0xc8, 0xe9, 0x20, 0x16, 0xdc, + + 0xa2, 0x03, 0xac, 0x07, 0x80, 0xb9, 0x00, 0x80, + 0xdd, 0x0c, 0xdf, 0xd0, 0x2e, 0xc8, 0xca, 0x10, + + 0xf4, 0xa6, 0xf4, 0xa4, 0xf4, 0xc8, 0xc0, 0x10, + 0xb0, 0x25, 0x98, 0x49, 0xff, 0x85, 0xfa, 0xa9, + + 0x7f, 0x85, 0xfb, 0x8c, 0x30, 0xfe, 0xb1, 0xfa, + 0x8e, 0x30, 0xfe, 0xd1, 0xfa, 0xd0, 0xe6, 0xe6, + + 0xfa, 0xd0, 0xf0, 0xe6, 0xfb, 0xa5, 0xfb, 0xc9, + 0x84, 0x90, 0xe8, 0xa6, 0xf4, 0x10, 0x0d, 0xad, + + 0x06, 0x80, 0x9d, 0xa1, 0x02, 0x29, 0x8f, 0xd0, + 0x03, 0x8e, 0x4b, 0x02, 0xe8, 0xe0, 0x10, 0x90, + + 0xac, 0x2c, 0x40, 0xfe, 0x30, 0x11, 0xce, 0x7b, + 0x02, 0xa0, 0xff, 0x20, 0x7f, 0xee, 0xca, 0xd0, + + 0xf8, 0x8e, 0x48, 0xfe, 0x8e, 0x49, 0xfe, 0xad, + 0x8f, 0x02, 0x20, 0x00, 0xc3, 0xa0, 0xca, 0x20, + + 0xf1, 0xe4, 0x20, 0xd9, 0xea, 0x20, 0x40, 0xf1, + 0xa9, 0x81, 0x8d, 0xe0, 0xfe, 0xad, 0xe0, 0xfe, + + 0x6a, 0x90, 0x0a, 0xa2, 0xff, 0x20, 0x68, 0xf1, + 0xd0, 0x03, 0xce, 0x7a, 0x02, 0xa0, 0x0e, 0xa2, + + 0x01, 0x20, 0x68, 0xf1, 0xa2, 0x02, 0x20, 0x68, + 0xf1, 0x8c, 0x43, 0x02, 0x8c, 0x44, 0x02, 0xa2, + + 0xfe, 0xac, 0x7a, 0x02, 0x20, 0x68, 0xf1, 0x2d, + 0x67, 0x02, 0x10, 0x1b, 0xa0, 0x02, 0x20, 0xa9, + + 0xde, 0xad, 0x8d, 0x02, 0xf0, 0x0c, 0xa0, 0x16, + 0x2c, 0x8e, 0x02, 0x30, 0x02, 0xa0, 0x11, 0x20, + + 0xa9, 0xde, 0xa0, 0x1b, 0x20, 0xa9, 0xde, 0x38, + 0x20, 0xd9, 0xea, 0x20, 0xd9, 0xe9, 0x08, 0x68, + + 0x4a, 0x4a, 0x4a, 0x4a, 0x4d, 0x8f, 0x02, 0x29, + 0x08, 0xa8, 0xa2, 0x03, 0x20, 0x68, 0xf1, 0xf0, + + 0x1d, 0x98, 0xd0, 0x14, 0xa9, 0x8d, 0x20, 0x35, + 0xf1, 0xa2, 0xd2, 0xa0, 0xea, 0xce, 0x67, 0x02, + + 0x20, 0xf7, 0xff, 0xee, 0x67, 0x02, 0xd0, 0x06, + 0xa9, 0x00, 0xaa, 0x20, 0x37, 0xf1, 0xad, 0x8d, + + 0x02, 0xd0, 0x05, 0xae, 0x8c, 0x02, 0x10, 0x1e, + 0xa2, 0x0f, 0xbd, 0xa1, 0x02, 0x2a, 0x30, 0x16, + + 0xca, 0x10, 0xf7, 0xa9, 0x00, 0x2c, 0x7a, 0x02, + 0x30, 0x2e, 0x00, 0xf9, 0x4c, 0x61, 0x6e, 0x67, + + 0x75, 0x61, 0x67, 0x65, 0x3f, 0x00, 0x18, 0x08, + 0x8e, 0x8c, 0x02, 0x20, 0x16, 0xdc, 0xa9, 0x80, + + 0xa0, 0x08, 0x20, 0xab, 0xde, 0x84, 0xfd, 0x20, + 0xe7, 0xff, 0x20, 0xe7, 0xff, 0x28, 0xa9, 0x01, + + 0x2c, 0x7a, 0x02, 0x30, 0x03, 0x4c, 0x00, 0x80, + 0x4c, 0x00, 0x04, 0xa6, 0xf4, 0x84, 0xf4, 0x8c, + + 0x30, 0xfe, 0xa0, 0x00, 0xb1, 0xf6, 0x86, 0xf4, + 0x8e, 0x30, 0xfe, 0x60, 0x85, 0xfc, 0x68, 0x48, + + 0x29, 0x10, 0xd0, 0x03, 0x6c, 0x04, 0x02, 0x8a, + 0x48, 0xba, 0xbd, 0x03, 0x01, 0xd8, 0x38, 0xe9, + + 0x01, 0x85, 0xfd, 0xbd, 0x04, 0x01, 0xe9, 0x00, + 0x85, 0xfe, 0xa5, 0xf4, 0x8d, 0x4a, 0x02, 0x86, + + 0xf0, 0xa2, 0x06, 0x20, 0x68, 0xf1, 0xae, 0x8c, + 0x02, 0x20, 0x16, 0xdc, 0x68, 0xaa, 0xa5, 0xfc, + + 0x58, 0x6c, 0x02, 0x02, 0xa0, 0x00, 0x20, 0xb1, + 0xde, 0xad, 0x67, 0x02, 0x6a, 0xb0, 0xfe, 0x20, + + 0xe7, 0xff, 0x20, 0xe7, 0xff, 0x4c, 0xb8, 0xdb, + 0x38, 0x6e, 0x4f, 0x02, 0x2c, 0x50, 0x02, 0x10, + + 0x07, 0x20, 0x41, 0xe7, 0xa2, 0x00, 0xb0, 0x02, + 0xa2, 0x40, 0x4c, 0x7a, 0xe1, 0xac, 0x09, 0xfe, + + 0x29, 0x3a, 0xd0, 0x34, 0xae, 0x5c, 0x02, 0xd0, + 0x09, 0xe8, 0x20, 0xf3, 0xe4, 0x20, 0x41, 0xe7, + + 0x90, 0xe6, 0x60, 0xd8, 0xa5, 0xfc, 0x48, 0x8a, + 0x48, 0x98, 0x48, 0xa9, 0xde, 0x48, 0xa9, 0x81, + + 0x48, 0xb8, 0xad, 0x08, 0xfe, 0x70, 0x02, 0x10, + 0x5d, 0xa6, 0xea, 0xca, 0x30, 0x30, 0x70, 0x2d, + + 0x4c, 0x88, 0xf5, 0xac, 0x09, 0xfe, 0x2a, 0x0a, + 0xaa, 0x98, 0xa0, 0x07, 0x4c, 0x94, 0xe4, 0xa2, + + 0x02, 0x20, 0x60, 0xe4, 0x90, 0x10, 0xad, 0x85, + 0x02, 0xc9, 0x02, 0xd0, 0x9b, 0xe8, 0x20, 0x60, + + 0xe4, 0x6e, 0xd2, 0x02, 0x30, 0x92, 0x8d, 0x09, + 0xfe, 0xa9, 0xe7, 0x85, 0xea, 0x60, 0x2d, 0x78, + + 0x02, 0x4a, 0x90, 0x07, 0x70, 0x05, 0xac, 0x50, + 0x02, 0x30, 0x92, 0x4a, 0x6a, 0xb0, 0xc4, 0x30, + + 0xce, 0x70, 0xea, 0xa2, 0x05, 0x20, 0x68, 0xf1, + 0xf0, 0xe3, 0x68, 0x68, 0x68, 0xa8, 0x68, 0xaa, + + 0x68, 0x85, 0xfc, 0x6c, 0x06, 0x02, 0xad, 0x4d, + 0xfe, 0x10, 0x3c, 0x2d, 0x79, 0x02, 0x2d, 0x4e, + + 0xfe, 0x6a, 0x6a, 0x90, 0x54, 0xce, 0x40, 0x02, + 0xa5, 0xea, 0x10, 0x02, 0xe6, 0xea, 0xad, 0x51, + + 0x02, 0xf0, 0x1a, 0xce, 0x51, 0x02, 0xd0, 0x15, + 0xae, 0x52, 0x02, 0xad, 0x48, 0x02, 0x4a, 0x90, + + 0x03, 0xae, 0x53, 0x02, 0x2a, 0x49, 0x01, 0x20, + 0x00, 0xea, 0x8e, 0x51, 0x02, 0xa0, 0x04, 0x20, + + 0x94, 0xe4, 0xa9, 0x02, 0x4c, 0x6e, 0xde, 0xad, + 0x6d, 0xfe, 0x10, 0xa7, 0x2d, 0x77, 0x02, 0x2d, + + 0x6e, 0xfe, 0x6a, 0x6a, 0x90, 0x9d, 0xac, 0x85, + 0x02, 0x88, 0xd0, 0x97, 0xa9, 0x02, 0x8d, 0x6d, + + 0xfe, 0x8d, 0x6e, 0xfe, 0xa2, 0x03, 0x4c, 0x3a, + 0xe1, 0x2a, 0x2a, 0x2a, 0x2a, 0x10, 0x5b, 0xa9, + + 0x20, 0xa2, 0x00, 0x8d, 0x4d, 0xfe, 0x8e, 0x49, + 0xfe, 0xa2, 0x08, 0x86, 0xfb, 0x20, 0x5b, 0xe4, + + 0x6e, 0xd7, 0x02, 0x30, 0x44, 0xa8, 0xf0, 0x05, + 0x20, 0x6d, 0xee, 0x30, 0x3c, 0x20, 0x60, 0xe4, + + 0x85, 0xf5, 0x20, 0x60, 0xe4, 0x85, 0xf7, 0x20, + 0x60, 0xe4, 0x85, 0xf6, 0xa4, 0xf5, 0xf0, 0x1b, + + 0x10, 0x16, 0x24, 0xf5, 0x70, 0x05, 0x20, 0xbb, + 0xee, 0x50, 0x07, 0x06, 0xf6, 0x26, 0xf7, 0x20, + + 0x3b, 0xee, 0xac, 0x61, 0x02, 0x4c, 0x7f, 0xee, + 0x20, 0x7f, 0xee, 0xa4, 0xf6, 0x20, 0x7f, 0xee, + + 0xa4, 0xf7, 0x20, 0x7f, 0xee, 0x46, 0xfb, 0xd0, + 0xb4, 0x60, 0x90, 0x7b, 0xa9, 0x40, 0x8d, 0x4d, + + 0xfe, 0xad, 0x83, 0x02, 0xaa, 0x49, 0x0f, 0x48, + 0xa8, 0xbd, 0x91, 0x02, 0x69, 0x00, 0x99, 0x91, + + 0x02, 0xca, 0xf0, 0x03, 0x88, 0xd0, 0xf2, 0x68, + 0x8d, 0x83, 0x02, 0xa2, 0x05, 0xfe, 0x9b, 0x02, + + 0xd0, 0x08, 0xca, 0xd0, 0xf8, 0xa0, 0x05, 0x20, + 0x94, 0xe4, 0xad, 0xb1, 0x02, 0xd0, 0x08, 0xad, + + 0xb2, 0x02, 0xf0, 0x06, 0xce, 0xb2, 0x02, 0xce, + 0xb1, 0x02, 0x2c, 0xce, 0x02, 0x10, 0x0b, 0xee, + + 0xce, 0x02, 0x58, 0x20, 0x47, 0xeb, 0x78, 0xce, + 0xce, 0x02, 0x2c, 0xd7, 0x02, 0x30, 0x0c, 0x20, + + 0x6d, 0xee, 0x49, 0xa0, 0xc9, 0x60, 0x90, 0x03, + 0x20, 0x79, 0xdd, 0x2c, 0xb7, 0xd9, 0x20, 0xa2, + + 0xdc, 0xa5, 0xec, 0x05, 0xed, 0x2d, 0x42, 0x02, + 0xf0, 0x04, 0x38, 0x20, 0x65, 0xf0, 0x20, 0x9b, + + 0xe1, 0x2c, 0xc0, 0xfe, 0x70, 0x04, 0x60, 0x2a, + 0x10, 0x28, 0xae, 0x4c, 0x02, 0xf0, 0x1d, 0xad, + + 0xc2, 0xfe, 0x9d, 0xb5, 0x02, 0xad, 0xc1, 0xfe, + 0x9d, 0xb9, 0x02, 0x8e, 0xbe, 0x02, 0xa0, 0x03, + + 0x20, 0x94, 0xe4, 0xca, 0xd0, 0x03, 0xae, 0x4d, + 0x02, 0x20, 0x8f, 0xde, 0xa9, 0x10, 0x8d, 0x4d, + + 0xfe, 0x60, 0x2a, 0x2a, 0x2a, 0x2a, 0x10, 0x07, + 0x20, 0x65, 0xf0, 0xa9, 0x01, 0xd0, 0xef, 0x4c, + + 0xf3, 0xdc, 0x68, 0xa8, 0x68, 0xaa, 0x68, 0x85, + 0xfc, 0xa5, 0xfc, 0x40, 0x8c, 0xbe, 0x02, 0xe0, + + 0x05, 0x90, 0x02, 0xa2, 0x04, 0x8e, 0x4c, 0x02, + 0xac, 0x4e, 0x02, 0x88, 0x98, 0x29, 0x08, 0x18, + + 0x6d, 0x4c, 0x02, 0xe9, 0x00, 0x8d, 0xc0, 0xfe, + 0x60, 0xa9, 0xc3, 0x85, 0xfe, 0xa9, 0x00, 0x85, + + 0xfd, 0xc8, 0xb1, 0xfd, 0x20, 0xe3, 0xff, 0xaa, + 0xd0, 0xf7, 0x60, 0x8e, 0xb1, 0x02, 0x8c, 0xb2, + + 0x02, 0xa9, 0xff, 0xd0, 0x02, 0xa9, 0x00, 0x85, + 0xe6, 0x8a, 0x48, 0x98, 0x48, 0xac, 0x56, 0x02, + + 0xf0, 0x14, 0x38, 0x66, 0xeb, 0x20, 0xd7, 0xff, + 0x08, 0x46, 0xeb, 0x28, 0x90, 0x25, 0xa9, 0x00, + + 0x8d, 0x56, 0x02, 0x20, 0xce, 0xff, 0x24, 0xff, + 0x30, 0x16, 0xae, 0x41, 0x02, 0x20, 0x77, 0xe5, + + 0x90, 0x11, 0x24, 0xe6, 0x50, 0xf0, 0xad, 0xb1, + 0x02, 0x0d, 0xb2, 0x02, 0xd0, 0xe8, 0xb0, 0x05, + + 0x38, 0xa9, 0x1b, 0x85, 0xe6, 0x68, 0xa8, 0x68, + 0xaa, 0xa5, 0xe6, 0x60, 0x29, 0x43, 0x28, 0x00, + + 0x2e, 0xe0, 0x31, 0x05, 0x46, 0x58, 0xe3, 0x42, + 0xff, 0x42, 0x41, 0x53, 0x49, 0x43, 0xe0, 0x18, + + 0x00, 0x43, 0x41, 0x54, 0xe0, 0x31, 0x05, 0x43, + 0x4f, 0x44, 0x45, 0xe3, 0x48, 0x88, 0x45, 0x58, + + 0x45, 0x43, 0xf6, 0x8d, 0x00, 0x48, 0x45, 0x4c, + 0x50, 0xf0, 0xb9, 0xff, 0x4b, 0x45, 0x59, 0xe3, + + 0x27, 0xff, 0x4c, 0x4f, 0x41, 0x44, 0xe2, 0x3c, + 0x00, 0x4c, 0x49, 0x4e, 0x45, 0xe6, 0x59, 0x01, + + 0x4d, 0x4f, 0x54, 0x4f, 0x52, 0xe3, 0x48, 0x89, + 0x4f, 0x50, 0x54, 0xe3, 0x48, 0x8b, 0x52, 0x55, + + 0x4e, 0xe0, 0x31, 0x04, 0x52, 0x4f, 0x4d, 0xe3, + 0x48, 0x8d, 0x53, 0x41, 0x56, 0x45, 0xe2, 0x3e, + + 0x00, 0x53, 0x50, 0x4f, 0x4f, 0x4c, 0xe2, 0x81, + 0x00, 0x54, 0x41, 0x50, 0x45, 0xe3, 0x48, 0x8c, + + 0x54, 0x56, 0xe3, 0x48, 0x90, 0xe0, 0x31, 0x03, + 0x00, 0x86, 0xf2, 0x84, 0xf3, 0xa9, 0x08, 0x20, + + 0x31, 0xe0, 0xa0, 0x00, 0xb1, 0xf2, 0xc9, 0x0d, + 0xf0, 0x04, 0xc8, 0xd0, 0xf7, 0x60, 0xa0, 0xff, + + 0x20, 0x39, 0xe0, 0xf0, 0x72, 0xc9, 0x2a, 0xf0, + 0xf7, 0x20, 0x3a, 0xe0, 0xf0, 0x69, 0xc9, 0x7c, + + 0xf0, 0x65, 0xc9, 0x2f, 0xd0, 0x08, 0xc8, 0x20, + 0x09, 0xe0, 0xa9, 0x02, 0xd0, 0x73, 0x84, 0xe6, + + 0xa2, 0x00, 0xf0, 0x13, 0x5d, 0x10, 0xdf, 0x29, + 0xdf, 0xd0, 0x17, 0xc8, 0x18, 0xb0, 0x25, 0xe8, + + 0xb1, 0xf2, 0x20, 0xe3, 0xe4, 0x90, 0xed, 0xbd, + 0x10, 0xdf, 0x30, 0x16, 0xb1, 0xf2, 0xc9, 0x2e, + + 0xf0, 0x04, 0x18, 0xa4, 0xe6, 0x88, 0xc8, 0xe8, + 0xe8, 0xbd, 0x0e, 0xdf, 0xf0, 0x33, 0x10, 0xf8, + + 0x30, 0xdb, 0xe8, 0xe8, 0xca, 0xca, 0x48, 0xbd, + 0x11, 0xdf, 0x48, 0x20, 0x3a, 0xe0, 0x18, 0x08, + + 0x20, 0x04, 0xe0, 0x40, 0xbd, 0x12, 0xdf, 0x30, + 0x0e, 0x98, 0xbc, 0x12, 0xdf, 0x18, 0x65, 0xf2, + + 0xaa, 0x98, 0xa4, 0xf3, 0x90, 0x01, 0xc8, 0x60, + 0xae, 0x4b, 0x02, 0x30, 0x04, 0x38, 0x4c, 0xe7, + + 0xdb, 0xa4, 0xe6, 0xa2, 0x04, 0x20, 0x68, 0xf1, + 0xf0, 0xed, 0xa5, 0xe6, 0x20, 0x0d, 0xe0, 0xa9, + + 0x03, 0x6c, 0x1e, 0x02, 0x0a, 0x29, 0x01, 0x10, + 0xf8, 0xc8, 0xb1, 0xf2, 0xc9, 0x20, 0xf0, 0xf9, + + 0xc9, 0x0d, 0x60, 0x90, 0xf5, 0x20, 0x3a, 0xe0, + 0xc9, 0x2c, 0xd0, 0xf4, 0xc8, 0x60, 0x20, 0x3a, + + 0xe0, 0x20, 0x7d, 0xe0, 0x90, 0x37, 0x85, 0xe6, + 0x20, 0x7c, 0xe0, 0x90, 0x19, 0xaa, 0xa5, 0xe6, + + 0x0a, 0xb0, 0x2a, 0x0a, 0xb0, 0x27, 0x65, 0xe6, + 0xb0, 0x23, 0x0a, 0xb0, 0x20, 0x85, 0xe6, 0x8a, + + 0x65, 0xe6, 0xb0, 0x19, 0x90, 0xe0, 0xa6, 0xe6, + 0xc9, 0x0d, 0x38, 0x60, 0xc8, 0xb1, 0xf2, 0xc9, + + 0x3a, 0xb0, 0x0a, 0xc9, 0x30, 0x90, 0x06, 0x29, + 0x0f, 0x60, 0x20, 0x45, 0xe0, 0x18, 0x60, 0x20, + + 0x7d, 0xe0, 0xb0, 0x0e, 0x29, 0xdf, 0xc9, 0x47, + 0xb0, 0xf0, 0xc9, 0x41, 0x90, 0xec, 0x08, 0xe9, + + 0x37, 0x28, 0xc8, 0x60, 0x48, 0x8a, 0x48, 0x98, + 0x48, 0xba, 0xbd, 0x03, 0x01, 0x48, 0x2c, 0x60, + + 0x02, 0x10, 0x08, 0xa8, 0xa9, 0x04, 0x20, 0x7e, + 0xe5, 0xb0, 0x52, 0x18, 0xa9, 0x02, 0x2c, 0x7c, + + 0x02, 0xd0, 0x05, 0x68, 0x48, 0x20, 0xc0, 0xc4, + 0xa9, 0x08, 0x2c, 0x7c, 0x02, 0xd0, 0x02, 0x90, + + 0x05, 0x68, 0x48, 0x20, 0x14, 0xe1, 0xad, 0x7c, + 0x02, 0x6a, 0x90, 0x1b, 0xa4, 0xea, 0x88, 0x10, + + 0x16, 0x68, 0x48, 0x08, 0x78, 0xa2, 0x02, 0x48, + 0x20, 0x5b, 0xe4, 0x90, 0x03, 0x20, 0x70, 0xe1, + + 0x68, 0xa2, 0x02, 0x20, 0xf8, 0xe1, 0x28, 0xa9, + 0x10, 0x2c, 0x7c, 0x02, 0xd0, 0x0f, 0xac, 0x57, + + 0x02, 0xf0, 0x0a, 0x68, 0x48, 0x38, 0x66, 0xeb, + 0x20, 0xd4, 0xff, 0x46, 0xeb, 0x68, 0x68, 0xa8, + + 0x68, 0xaa, 0x68, 0x60, 0x2c, 0x7c, 0x02, 0x70, + 0x20, 0xcd, 0x86, 0x02, 0xf0, 0x1b, 0x08, 0x78, + + 0xaa, 0xa9, 0x04, 0x2c, 0x7c, 0x02, 0xd0, 0x10, + 0x8a, 0xa2, 0x03, 0x20, 0xf8, 0xe1, 0xb0, 0x08, + + 0x2c, 0xd2, 0x02, 0x10, 0x03, 0x20, 0x3a, 0xe1, + 0x28, 0x60, 0xad, 0x85, 0x02, 0xf0, 0x6e, 0xc9, + + 0x01, 0xd0, 0x21, 0x20, 0x60, 0xe4, 0x6e, 0xd2, + 0x02, 0x30, 0x45, 0xa0, 0x82, 0x8c, 0x6e, 0xfe, + + 0x8d, 0x61, 0xfe, 0xad, 0x6c, 0xfe, 0x29, 0xf1, + 0x09, 0x0c, 0x8d, 0x6c, 0xfe, 0x09, 0x0e, 0x8d, + + 0x6c, 0xfe, 0xd0, 0x2c, 0xc9, 0x02, 0xd0, 0x29, + 0xa4, 0xea, 0x88, 0x10, 0x40, 0x4e, 0xd2, 0x02, + + 0x4e, 0x4f, 0x02, 0x20, 0x41, 0xe7, 0x90, 0x18, + 0xa2, 0x20, 0xa0, 0x9f, 0x08, 0x78, 0x98, 0x86, + + 0xfa, 0x2d, 0x50, 0x02, 0x45, 0xfa, 0xae, 0x50, + 0x02, 0x8d, 0x50, 0x02, 0x8d, 0x08, 0xfe, 0x28, + + 0x60, 0x18, 0xa9, 0x01, 0x20, 0xa2, 0xe1, 0x6e, + 0xd2, 0x02, 0x60, 0x2c, 0xd2, 0x02, 0x30, 0xfa, + + 0xa9, 0x00, 0xa2, 0x03, 0xac, 0x85, 0x02, 0x20, + 0x7e, 0xe5, 0x6c, 0x22, 0x02, 0x18, 0x48, 0x08, + + 0x78, 0xb0, 0x08, 0xbd, 0xad, 0xe9, 0x10, 0x03, + 0x20, 0xa2, 0xec, 0x38, 0x7e, 0xcf, 0x02, 0xe0, + + 0x02, 0xb0, 0x08, 0xa9, 0x00, 0x8d, 0x68, 0x02, + 0x8d, 0x6a, 0x02, 0x20, 0x3b, 0xe7, 0x28, 0x68, + + 0x60, 0x50, 0x07, 0xbd, 0xd8, 0x02, 0x9d, 0xe1, + 0x02, 0x60, 0x08, 0x78, 0x08, 0x38, 0xbd, 0xe1, + + 0x02, 0xfd, 0xd8, 0x02, 0xb0, 0x04, 0x38, 0xfd, + 0x47, 0xe4, 0x28, 0x90, 0x06, 0x18, 0x7d, 0x47, + + 0xe4, 0x49, 0xff, 0xa0, 0x00, 0xaa, 0x28, 0x60, + 0x78, 0x20, 0xb0, 0xe4, 0x90, 0x0f, 0x20, 0xea, + + 0xe9, 0x08, 0x48, 0x20, 0xeb, 0xee, 0x68, 0x28, + 0x30, 0x03, 0x58, 0xb0, 0xeb, 0x60, 0x48, 0xa9, + + 0x00, 0x9d, 0xee, 0x02, 0x9d, 0xef, 0x02, 0x9d, + 0xf0, 0x02, 0x9d, 0xf1, 0x02, 0x68, 0x60, 0x84, + + 0xe6, 0x2a, 0x2a, 0x2a, 0x2a, 0xa0, 0x04, 0x2a, + 0x3e, 0xee, 0x02, 0x3e, 0xef, 0x02, 0x3e, 0xf0, + + 0x02, 0x3e, 0xf1, 0x02, 0xb0, 0x31, 0x88, 0xd0, + 0xee, 0xa4, 0xe6, 0x60, 0xa9, 0xff, 0x86, 0xf2, + + 0x84, 0xf3, 0x8e, 0xee, 0x02, 0x8c, 0xef, 0x02, + 0x48, 0xa2, 0x02, 0x20, 0x0e, 0xe2, 0xa0, 0xff, + + 0x8c, 0xf4, 0x02, 0xc8, 0x20, 0x1d, 0xea, 0x20, + 0x2f, 0xea, 0x90, 0xfb, 0x68, 0x48, 0xf0, 0x62, + + 0x20, 0xad, 0xe2, 0xb0, 0x3b, 0xf0, 0x3e, 0x00, + 0xfc, 0x42, 0x61, 0x64, 0x20, 0x61, 0x64, 0x64, + + 0x72, 0x65, 0x73, 0x73, 0x00, 0xa2, 0x10, 0x20, + 0x68, 0xf1, 0xf0, 0x23, 0x20, 0x8b, 0xf6, 0xa9, + + 0x00, 0x08, 0x84, 0xe6, 0xac, 0x57, 0x02, 0x8d, + 0x57, 0x02, 0xf0, 0x03, 0x20, 0xce, 0xff, 0xa4, + + 0xe6, 0x28, 0xf0, 0x0b, 0xa9, 0x80, 0x20, 0xce, + 0xff, 0xa8, 0xf0, 0x74, 0x8d, 0x57, 0x02, 0x60, + + 0xd0, 0x6e, 0xee, 0xf4, 0x02, 0xa2, 0xee, 0xa0, + 0x02, 0x68, 0x4c, 0xdd, 0xff, 0x20, 0x3a, 0xe0, + + 0x20, 0x8f, 0xe0, 0x90, 0x0c, 0x20, 0x0e, 0xe2, + 0x20, 0x1f, 0xe2, 0x20, 0x8f, 0xe0, 0xb0, 0xf8, + + 0x38, 0x60, 0xa2, 0x0a, 0x20, 0xad, 0xe2, 0x90, + 0x47, 0xb8, 0xb1, 0xf2, 0xc9, 0x2b, 0xd0, 0x04, + + 0x2c, 0xb7, 0xd9, 0xc8, 0xa2, 0x0e, 0x20, 0xad, + 0xe2, 0x90, 0x35, 0x08, 0x50, 0x0f, 0xa2, 0xfc, + + 0x18, 0xbd, 0xfc, 0x01, 0x7d, 0x00, 0x02, 0x9d, + 0x00, 0x02, 0xe8, 0xd0, 0xf4, 0xa2, 0x03, 0xbd, + + 0xf8, 0x02, 0x9d, 0xf4, 0x02, 0x9d, 0xf0, 0x02, + 0xca, 0x10, 0xf4, 0x28, 0xf0, 0xa7, 0xa2, 0x06, + + 0x20, 0xad, 0xe2, 0x90, 0x0b, 0xf0, 0x9e, 0xa2, + 0x02, 0x20, 0xad, 0xe2, 0x90, 0x02, 0xf0, 0x95, + + 0x00, 0xfe, 0x42, 0x61, 0x64, 0x20, 0x63, 0x6f, + 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x00, 0xfb, 0x42, + + 0x61, 0x64, 0x20, 0x6b, 0x65, 0x79, 0x00, 0x20, + 0x4e, 0xe0, 0x90, 0xf1, 0xe0, 0x10, 0xb0, 0xed, + + 0x20, 0x45, 0xe0, 0x08, 0xae, 0x10, 0x0b, 0x98, + 0x48, 0x20, 0xd1, 0xe3, 0x68, 0xa8, 0x28, 0xd0, + + 0x36, 0x60, 0x20, 0x4e, 0xe0, 0x90, 0xc9, 0x8a, + 0x48, 0xa9, 0x00, 0x85, 0xe5, 0x85, 0xe4, 0x20, + + 0x43, 0xe0, 0xf0, 0x18, 0x20, 0x4e, 0xe0, 0x90, + 0xb7, 0x86, 0xe5, 0x20, 0x45, 0xe0, 0xf0, 0x0c, + + 0x20, 0x4e, 0xe0, 0x90, 0xab, 0x86, 0xe4, 0x20, + 0x3a, 0xe0, 0xd0, 0xa4, 0xa4, 0xe4, 0xa6, 0xe5, + + 0x68, 0x20, 0xf4, 0xff, 0x70, 0x9a, 0x60, 0x38, + 0x20, 0x1e, 0xea, 0x20, 0x2f, 0xea, 0xb0, 0x08, + + 0xe8, 0xf0, 0x9a, 0x9d, 0x00, 0x0b, 0x90, 0xf3, + 0xd0, 0x93, 0x08, 0x78, 0x20, 0xd1, 0xe3, 0xa2, + + 0x10, 0xe4, 0xe6, 0xf0, 0x0e, 0xbd, 0x00, 0x0b, + 0xd9, 0x00, 0x0b, 0xd0, 0x06, 0xad, 0x10, 0x0b, + + 0x9d, 0x00, 0x0b, 0xca, 0x10, 0xeb, 0x28, 0x60, + 0x08, 0x78, 0xad, 0x10, 0x0b, 0x38, 0xf9, 0x00, + + 0x0b, 0x85, 0xfb, 0x8a, 0x48, 0xa2, 0x10, 0xbd, + 0x00, 0x0b, 0x38, 0xf9, 0x00, 0x0b, 0x90, 0x08, + + 0xf0, 0x06, 0xc5, 0xfb, 0xb0, 0x02, 0x85, 0xfb, + 0xca, 0x10, 0xec, 0x68, 0xaa, 0xa5, 0xfb, 0x28, + + 0x60, 0x08, 0x78, 0x8a, 0x48, 0xa4, 0xe6, 0x20, + 0xa8, 0xe3, 0xb9, 0x00, 0x0b, 0xa8, 0x18, 0x65, + + 0xfb, 0xaa, 0x85, 0xfa, 0xad, 0x68, 0x02, 0xf0, + 0x0d, 0x00, 0xfa, 0x4b, 0x65, 0x79, 0x20, 0x69, + + 0x6e, 0x20, 0x75, 0x73, 0x65, 0x00, 0xce, 0x84, + 0x02, 0x68, 0x38, 0xe5, 0xfa, 0x85, 0xfa, 0xf0, + + 0x0c, 0xbd, 0x01, 0x0b, 0x99, 0x01, 0x0b, 0xc8, + 0xe8, 0xc6, 0xfa, 0xd0, 0xf4, 0x98, 0x48, 0xa4, + + 0xe6, 0xa2, 0x10, 0xbd, 0x00, 0x0b, 0xd9, 0x00, + 0x0b, 0x90, 0x07, 0xf0, 0x05, 0xe5, 0xfb, 0x9d, + + 0x00, 0x0b, 0xca, 0x10, 0xee, 0xad, 0x10, 0x0b, + 0x99, 0x00, 0x0b, 0x68, 0x8d, 0x10, 0x0b, 0xaa, + + 0xee, 0x84, 0x02, 0x28, 0x60, 0x03, 0x0a, 0x08, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x09, 0x00, 0x00, + + 0xc0, 0xc0, 0x50, 0x60, 0x70, 0x80, 0x00, 0xe0, + 0x00, 0x40, 0xc0, 0xf0, 0xf0, 0xf0, 0xf0, 0xc0, + + 0xbd, 0x3e, 0xe4, 0x85, 0xfa, 0xbd, 0x35, 0xe4, + 0x85, 0xfb, 0x60, 0x2c, 0xb7, 0xd9, 0x70, 0x01, + + 0xb8, 0x6c, 0x2c, 0x02, 0x08, 0x78, 0xbd, 0xd8, + 0x02, 0xdd, 0xe1, 0x02, 0xf0, 0x72, 0xa8, 0x20, + + 0x50, 0xe4, 0xb1, 0xfa, 0x70, 0x1b, 0x48, 0xc8, + 0x98, 0xd0, 0x03, 0xbd, 0x47, 0xe4, 0x9d, 0xd8, + + 0x02, 0xe0, 0x02, 0x90, 0x0a, 0xdd, 0xe1, 0x02, + 0xd0, 0x05, 0xa0, 0x00, 0x20, 0x94, 0xe4, 0x68, + + 0xa8, 0x28, 0x18, 0x60, 0x08, 0x78, 0x48, 0x85, + 0xfa, 0xb9, 0xbf, 0x02, 0xf0, 0x41, 0x98, 0xa4, + + 0xfa, 0x20, 0xa5, 0xf0, 0x68, 0x28, 0x18, 0x60, + 0x98, 0xa0, 0x02, 0x20, 0x94, 0xe4, 0xa8, 0x98, + + 0x6c, 0x2a, 0x02, 0x08, 0x78, 0x48, 0xbc, 0xe1, + 0x02, 0xc8, 0xd0, 0x03, 0xbc, 0x47, 0xe4, 0x98, + + 0xdd, 0xd8, 0x02, 0xf0, 0x0f, 0xbc, 0xe1, 0x02, + 0x9d, 0xe1, 0x02, 0x20, 0x50, 0xe4, 0x68, 0x91, + + 0xfa, 0x28, 0x18, 0x60, 0x68, 0xe0, 0x02, 0xb0, + 0x07, 0xa0, 0x01, 0x20, 0x94, 0xe4, 0x48, 0x68, + + 0x28, 0x38, 0x60, 0x48, 0x29, 0xdf, 0xc9, 0x41, + 0x90, 0x04, 0xc9, 0x5b, 0x90, 0x01, 0x38, 0x68, + + 0x60, 0xa2, 0x00, 0x8a, 0x2d, 0x45, 0x02, 0xd0, + 0xb6, 0x98, 0x4d, 0x6c, 0x02, 0x0d, 0x75, 0x02, + + 0xd0, 0xa6, 0xad, 0x58, 0x02, 0x6a, 0x98, 0xb0, + 0x0a, 0xa0, 0x06, 0x20, 0x94, 0xe4, 0x90, 0x03, + + 0x20, 0x74, 0xe6, 0x18, 0x60, 0x6a, 0x68, 0xb0, + 0x79, 0x98, 0x48, 0x4a, 0x4a, 0x4a, 0x4a, 0x49, + + 0x04, 0xa8, 0xb9, 0x65, 0x02, 0xc9, 0x01, 0xf0, + 0x6b, 0x68, 0x90, 0x0d, 0x29, 0x0f, 0x18, 0x79, + + 0x65, 0x02, 0x18, 0x60, 0x20, 0x6f, 0xe8, 0x68, + 0xaa, 0x20, 0x60, 0xe4, 0xb0, 0x55, 0x48, 0xe0, + + 0x01, 0xd0, 0x06, 0x20, 0x73, 0xe1, 0xa2, 0x01, + 0x38, 0x68, 0x90, 0x05, 0xac, 0x45, 0x02, 0xd0, + + 0x41, 0xa8, 0x10, 0x3e, 0x29, 0x0f, 0xc9, 0x0b, + 0x90, 0xbf, 0x69, 0x7b, 0x48, 0xad, 0x7d, 0x02, + + 0xd0, 0xb3, 0xad, 0x7c, 0x02, 0x6a, 0x6a, 0x68, + 0xb0, 0xcf, 0xc9, 0x87, 0xf0, 0x38, 0xa8, 0x8a, + + 0x48, 0x98, 0x20, 0xce, 0xd8, 0x68, 0xaa, 0x2c, + 0x5f, 0x02, 0x10, 0x05, 0xa9, 0x06, 0x6c, 0x24, + + 0x02, 0xad, 0x68, 0x02, 0xf0, 0xb3, 0xac, 0xc9, + 0x02, 0xb9, 0x01, 0x0b, 0xee, 0xc9, 0x02, 0xce, + + 0x68, 0x02, 0x18, 0x60, 0x68, 0x29, 0x0f, 0xa8, + 0x20, 0xa8, 0xe3, 0x8d, 0x68, 0x02, 0xb9, 0x00, + + 0x0b, 0x8d, 0xc9, 0x02, 0xd0, 0xd1, 0x8a, 0x48, + 0x20, 0x05, 0xd9, 0xa8, 0xf0, 0x86, 0x68, 0xaa, + + 0x98, 0x18, 0x60, 0x21, 0xe8, 0x88, 0xe9, 0xd3, + 0xe6, 0x97, 0xe9, 0x97, 0xe9, 0x76, 0xe9, 0x88, + + 0xe9, 0x8b, 0xe6, 0x89, 0xe6, 0xb0, 0xe6, 0xb2, + 0xe6, 0x95, 0xe9, 0x8c, 0xe9, 0xf9, 0xe6, 0xfa, + + 0xe6, 0xa8, 0xf0, 0x06, 0xe7, 0x8c, 0xde, 0xc8, + 0xe9, 0xb6, 0xe9, 0x07, 0xcd, 0xb4, 0xf0, 0x6c, + + 0xe8, 0xd9, 0xe9, 0x75, 0xe2, 0x45, 0xf0, 0xcf, + 0xf0, 0xcd, 0xf0, 0x97, 0xe1, 0x73, 0xe6, 0x74, + + 0xe6, 0x5c, 0xe6, 0x35, 0xe0, 0x4f, 0xe7, 0x13, + 0xe7, 0x29, 0xe7, 0x85, 0xf0, 0x23, 0xd9, 0x26, + + 0xd9, 0x47, 0xd6, 0xc2, 0xd7, 0x57, 0xe6, 0x7f, + 0xe6, 0xaf, 0xe4, 0x34, 0xe0, 0x35, 0xf1, 0x35, + + 0xf1, 0xe7, 0xdb, 0x68, 0xf1, 0xe3, 0xea, 0x60, + 0xe4, 0xaa, 0xff, 0xf4, 0xea, 0xae, 0xff, 0xf9, + + 0xea, 0xb2, 0xff, 0xfe, 0xea, 0x5b, 0xe4, 0xf3, + 0xe4, 0xff, 0xe9, 0x10, 0xea, 0x7c, 0xe1, 0xa7, + + 0xff, 0x6d, 0xee, 0x7f, 0xee, 0xc0, 0xe9, 0x9c, + 0xe9, 0x59, 0xe6, 0x02, 0xe9, 0xd5, 0xe8, 0xe8, + + 0xe8, 0xd1, 0xe8, 0xe4, 0xe8, 0x03, 0xe8, 0x0b, + 0xe8, 0x2d, 0xe8, 0xae, 0xe8, 0x35, 0xc7, 0xf3, + + 0xcb, 0x48, 0xc7, 0xe0, 0xc8, 0xce, 0xd5, 0xa9, + 0x00, 0x6c, 0x00, 0x02, 0xa2, 0x00, 0x24, 0xff, + + 0x10, 0x11, 0xad, 0x76, 0x02, 0xd0, 0x0a, 0x58, + 0x8d, 0x69, 0x02, 0x20, 0x8d, 0xf6, 0x20, 0xaa, + + 0xf0, 0xa2, 0xff, 0x18, 0x66, 0xff, 0x2c, 0x7a, + 0x02, 0x30, 0x01, 0x60, 0x4c, 0x03, 0x04, 0xad, + + 0x82, 0x02, 0xa8, 0x2a, 0xe0, 0x01, 0x6a, 0x50, + 0x1e, 0xa9, 0x38, 0x49, 0x3f, 0x85, 0xfa, 0xac, + + 0x82, 0x02, 0xe0, 0x09, 0xb0, 0x17, 0x3d, 0xad, + 0xe9, 0x85, 0xfb, 0x98, 0x05, 0xfa, 0x45, 0xfa, + + 0x05, 0xfb, 0x09, 0x40, 0x4d, 0x5d, 0x02, 0x8d, + 0x82, 0x02, 0x8d, 0x10, 0xfe, 0x98, 0xaa, 0x60, + + 0xc8, 0x18, 0xb9, 0x52, 0x02, 0x48, 0x8a, 0x99, + 0x52, 0x02, 0x68, 0xa8, 0xad, 0x51, 0x02, 0xd0, + + 0x10, 0x8e, 0x51, 0x02, 0xad, 0x48, 0x02, 0x08, + 0x6a, 0x28, 0x2a, 0x8d, 0x48, 0x02, 0x8d, 0x20, + + 0xfe, 0x50, 0xda, 0x8a, 0x29, 0x01, 0x48, 0xad, + 0x50, 0x02, 0x2a, 0xe0, 0x01, 0x6a, 0xcd, 0x50, + + 0x02, 0x08, 0x8d, 0x50, 0x02, 0x8d, 0x08, 0xfe, + 0x20, 0x73, 0xe1, 0x28, 0xf0, 0x03, 0x2c, 0x09, + + 0xfe, 0xae, 0x41, 0x02, 0x68, 0x8d, 0x41, 0x02, + 0x60, 0x98, 0xe0, 0x0a, 0xb0, 0xb0, 0xbc, 0xbf, + + 0x02, 0x9d, 0xbf, 0x02, 0x50, 0xa7, 0xf0, 0x03, + 0x20, 0x8c, 0xde, 0xad, 0x4d, 0x02, 0x8e, 0x4d, + + 0x02, 0xaa, 0x60, 0x98, 0x30, 0x0b, 0x58, 0x20, + 0xbb, 0xde, 0xb0, 0x03, 0xaa, 0xa9, 0x00, 0xa8, + + 0x60, 0x8a, 0x49, 0x7f, 0xaa, 0x20, 0x68, 0xf0, + 0x2a, 0xa2, 0xff, 0xa0, 0xff, 0xb0, 0x02, 0xe8, + + 0xc8, 0x60, 0x8a, 0x49, 0xff, 0xaa, 0xe0, 0x02, + 0xb8, 0x50, 0x03, 0x2c, 0xb7, 0xd9, 0x6c, 0x2e, + + 0x02, 0x38, 0xa2, 0x01, 0x20, 0x38, 0xe7, 0xc0, + 0x01, 0xb0, 0x03, 0xec, 0x5b, 0x02, 0x60, 0x30, + + 0xe1, 0xf0, 0x0c, 0xe0, 0x05, 0xb0, 0xd2, 0xbc, + 0xb9, 0x02, 0xbd, 0xb5, 0x02, 0xaa, 0x60, 0xad, + + 0x40, 0xfe, 0x6a, 0x6a, 0x6a, 0x6a, 0x49, 0xff, + 0x29, 0x03, 0xac, 0xbe, 0x02, 0x8e, 0xbe, 0x02, + + 0xaa, 0x60, 0x48, 0x08, 0x78, 0x85, 0xef, 0x86, + 0xf0, 0x84, 0xf1, 0xa2, 0x07, 0xc9, 0x75, 0x90, + + 0x41, 0xc9, 0xa1, 0x90, 0x09, 0xc9, 0xa6, 0x90, + 0x3f, 0x18, 0xa9, 0xa1, 0x69, 0x00, 0x38, 0xe9, + + 0x5f, 0x0a, 0x38, 0x84, 0xf1, 0xa8, 0x2c, 0x5e, + 0x02, 0x10, 0x07, 0x8a, 0xb8, 0x20, 0x7e, 0xe5, + + 0x70, 0x1a, 0xb9, 0xb4, 0xe5, 0x85, 0xfb, 0xb9, + 0xb3, 0xe5, 0x85, 0xfa, 0xa5, 0xef, 0xa4, 0xf1, + + 0xb0, 0x04, 0xa0, 0x00, 0xb1, 0xf0, 0x38, 0xa6, + 0xf0, 0x20, 0x58, 0xf0, 0x6a, 0x28, 0x2a, 0x68, + + 0xb8, 0x60, 0xa0, 0x00, 0xc9, 0x16, 0x90, 0xc9, + 0x08, 0x08, 0x68, 0x68, 0x20, 0x68, 0xf1, 0xd0, + + 0x05, 0xa6, 0xf0, 0x4c, 0xbc, 0xe7, 0x28, 0x68, + 0x2c, 0xb7, 0xd9, 0x60, 0xa5, 0xeb, 0x30, 0x32, + + 0xa9, 0x08, 0x25, 0xe2, 0xd0, 0x04, 0xa9, 0x88, + 0x25, 0xbb, 0x60, 0x48, 0x08, 0x78, 0x85, 0xef, + + 0x86, 0xf0, 0x84, 0xf1, 0xa2, 0x08, 0xc9, 0xe0, + 0xb0, 0x90, 0xc9, 0x0e, 0xb0, 0xca, 0x69, 0x44, + + 0x0a, 0x90, 0x90, 0x20, 0x15, 0xe8, 0xa1, 0xf9, + 0x91, 0xf0, 0x60, 0x20, 0x15, 0xe8, 0xb1, 0xf0, + + 0x81, 0xf9, 0xa9, 0x00, 0x60, 0x85, 0xfa, 0xc8, + 0xb1, 0xf0, 0x85, 0xfb, 0xa0, 0x04, 0xa2, 0x01, + + 0x60, 0xd0, 0xfb, 0x00, 0xf7, 0x4f, 0x53, 0x20, + 0x31, 0x2e, 0x32, 0x30, 0x00, 0xc8, 0xb1, 0xf0, + + 0xc9, 0xff, 0xf0, 0x59, 0xc9, 0x20, 0xa2, 0x08, + 0xb0, 0x90, 0x88, 0x20, 0xc9, 0xe8, 0x09, 0x04, + + 0xaa, 0x90, 0x05, 0x20, 0xae, 0xe1, 0xa0, 0x01, + 0x20, 0xc9, 0xe8, 0x85, 0xfa, 0x08, 0xa0, 0x06, + + 0xb1, 0xf0, 0x48, 0xa0, 0x04, 0xb1, 0xf0, 0x48, + 0xa0, 0x02, 0xb1, 0xf0, 0x2a, 0x38, 0xe9, 0x02, + + 0x0a, 0x0a, 0x05, 0xfa, 0x20, 0xf8, 0xe1, 0x90, + 0x1e, 0x68, 0x68, 0x28, 0xa6, 0xd0, 0x60, 0x08, + + 0x78, 0xad, 0x63, 0x02, 0x29, 0x07, 0x09, 0x04, + 0xaa, 0xad, 0x64, 0x02, 0x20, 0xb0, 0xe4, 0xad, + + 0x66, 0x02, 0x48, 0xad, 0x65, 0x02, 0x48, 0x38, + 0x7e, 0x00, 0x08, 0x30, 0x17, 0x08, 0xc8, 0xb1, + + 0xf0, 0x48, 0xc8, 0xb1, 0xf0, 0x48, 0xa0, 0x00, + 0xb1, 0xf0, 0xa2, 0x08, 0x20, 0xf8, 0xe1, 0xb0, + + 0xc8, 0x6e, 0xd7, 0x02, 0x68, 0x20, 0xb0, 0xe4, + 0x68, 0x20, 0xb0, 0xe4, 0x28, 0x60, 0xe9, 0x01, + + 0x0a, 0x0a, 0x0a, 0x0a, 0x09, 0x0f, 0xaa, 0xa9, + 0x00, 0xa0, 0x10, 0xc0, 0x0e, 0xb0, 0x02, 0xb1, + + 0xf0, 0x9d, 0xc0, 0x08, 0xca, 0x88, 0xd0, 0xf3, + 0x60, 0xb1, 0xf0, 0xc9, 0x10, 0x29, 0x03, 0xc8, + + 0x60, 0xa2, 0x0f, 0xd0, 0x03, 0xae, 0x83, 0x02, + 0xa0, 0x04, 0xbd, 0x8d, 0x02, 0x91, 0xf0, 0xe8, + + 0x88, 0x10, 0xf7, 0x60, 0xa9, 0x0f, 0xd0, 0x06, + 0xad, 0x83, 0x02, 0x49, 0x0f, 0x18, 0x48, 0xaa, + + 0xa0, 0x04, 0xb1, 0xf0, 0x9d, 0x8d, 0x02, 0xe8, + 0x88, 0x10, 0xf7, 0x68, 0xb0, 0xe5, 0x8d, 0x83, + + 0x02, 0x60, 0xa0, 0x04, 0xb1, 0xf0, 0x99, 0xb1, + 0x02, 0x88, 0xc0, 0x02, 0xb0, 0xf6, 0xb1, 0xf0, + + 0x85, 0xe9, 0x88, 0x8c, 0x69, 0x02, 0xb1, 0xf0, + 0x85, 0xe8, 0x58, 0x90, 0x07, 0xa9, 0x07, 0x88, + + 0xc8, 0x20, 0xee, 0xff, 0x20, 0xe0, 0xff, 0xb0, + 0x49, 0xaa, 0xad, 0x7c, 0x02, 0x6a, 0x6a, 0x8a, + + 0xb0, 0x05, 0xae, 0x6a, 0x02, 0xd0, 0xea, 0xc9, + 0x7f, 0xd0, 0x07, 0xc0, 0x00, 0xf0, 0xe5, 0x88, + + 0xb0, 0xdf, 0xc9, 0x15, 0xd0, 0x0d, 0x98, 0xf0, + 0xdb, 0xa9, 0x7f, 0x20, 0xee, 0xff, 0x88, 0xd0, + + 0xfa, 0xf0, 0xd1, 0x91, 0xe8, 0xc9, 0x0d, 0xf0, + 0x13, 0xcc, 0xb3, 0x02, 0xb0, 0xbf, 0xcd, 0xb4, + + 0x02, 0x90, 0xbc, 0xcd, 0xb5, 0x02, 0xf0, 0xb8, + 0x90, 0xb6, 0xb0, 0xb3, 0x20, 0xe7, 0xff, 0x20, + + 0x7e, 0xe5, 0xa5, 0xff, 0x2a, 0x60, 0x58, 0x78, + 0x24, 0xff, 0x30, 0x30, 0x2c, 0xd2, 0x02, 0x10, + + 0xf5, 0x20, 0xa4, 0xe1, 0xa0, 0x00, 0x84, 0xf1, + 0x09, 0xf0, 0xd0, 0x0e, 0xd0, 0x07, 0xa2, 0x32, + + 0x8e, 0x54, 0x02, 0xa2, 0x08, 0x69, 0xcf, 0x18, + 0x69, 0xe9, 0x86, 0xf0, 0xa8, 0xb9, 0x90, 0x01, + + 0xaa, 0x25, 0xf1, 0x45, 0xf0, 0x99, 0x90, 0x01, + 0xb9, 0x91, 0x01, 0xa8, 0x60, 0x64, 0x7f, 0x5b, + + 0x6d, 0xc9, 0xf6, 0xd2, 0xe4, 0x40, 0xad, 0x40, + 0x02, 0x58, 0x78, 0xcd, 0x40, 0x02, 0xf0, 0xf9, + + 0xbc, 0x01, 0x03, 0xbd, 0x00, 0x03, 0xaa, 0x60, + 0xa9, 0x10, 0x8d, 0x84, 0x02, 0xa2, 0x00, 0x9d, + + 0x00, 0x0b, 0xe8, 0xd0, 0xfa, 0x8e, 0x84, 0x02, + 0x60, 0x08, 0x78, 0xa9, 0x40, 0x20, 0xea, 0xe9, + + 0x30, 0x05, 0x18, 0xb8, 0x20, 0x68, 0xf0, 0x28, + 0x2a, 0x60, 0x90, 0x09, 0xa0, 0x07, 0x8c, 0x40, + + 0xfe, 0x88, 0x8c, 0x40, 0xfe, 0x24, 0xff, 0x60, + 0x08, 0x78, 0x8d, 0x40, 0xfe, 0x28, 0x60, 0x8a, + + 0x08, 0x78, 0x8d, 0x48, 0x02, 0x8d, 0x20, 0xfe, + 0xad, 0x53, 0x02, 0x8d, 0x51, 0x02, 0x28, 0x60, + + 0x8a, 0x49, 0x07, 0x08, 0x78, 0x8d, 0x49, 0x02, + 0x8d, 0x21, 0xfe, 0x28, 0x60, 0x18, 0x66, 0xe4, + + 0x20, 0x3a, 0xe0, 0xc8, 0xc9, 0x22, 0xf0, 0x02, + 0x88, 0x18, 0x66, 0xe4, 0xc9, 0x0d, 0x60, 0xa9, + + 0x00, 0x85, 0xe5, 0xb1, 0xf2, 0xc9, 0x0d, 0xd0, + 0x06, 0x24, 0xe4, 0x30, 0x52, 0x10, 0x1b, 0xc9, + + 0x20, 0x90, 0x4c, 0xd0, 0x06, 0x24, 0xe4, 0x30, + 0x40, 0x50, 0x0f, 0xc9, 0x22, 0xd0, 0x10, 0x24, + + 0xe4, 0x10, 0x36, 0xc8, 0xb1, 0xf2, 0xc9, 0x22, + 0xf0, 0x2f, 0x20, 0x3a, 0xe0, 0x38, 0x60, 0xc9, + + 0x7c, 0xd0, 0x26, 0xc8, 0xb1, 0xf2, 0xc9, 0x7c, + 0xf0, 0x1f, 0xc9, 0x22, 0xf0, 0x1b, 0xc9, 0x21, + + 0xd0, 0x05, 0xc8, 0xa9, 0x80, 0xd0, 0xba, 0xc9, + 0x20, 0x90, 0x14, 0xc9, 0x3f, 0xf0, 0x08, 0x20, + + 0xbf, 0xea, 0x2c, 0xb7, 0xd9, 0x70, 0x03, 0xa9, + 0x7f, 0xb8, 0xc8, 0x05, 0xe5, 0x18, 0x60, 0x00, + + 0xfd, 0x42, 0x61, 0x64, 0x20, 0x73, 0x74, 0x72, + 0x69, 0x6e, 0x67, 0x00, 0xc9, 0x30, 0xf0, 0x1e, + + 0xc9, 0x40, 0xf0, 0x1a, 0x90, 0x12, 0xc9, 0x7f, + 0xf0, 0x14, 0xb0, 0x10, 0x49, 0x30, 0xc9, 0x6f, + + 0xf0, 0x04, 0xc9, 0x50, 0xd0, 0x02, 0x49, 0x1f, + 0xc9, 0x21, 0x90, 0x02, 0x49, 0x10, 0x60, 0xc9, + + 0x7f, 0xf0, 0x0e, 0xb0, 0xe7, 0xc9, 0x60, 0xd0, + 0x02, 0xa9, 0x5f, 0xc9, 0x40, 0x90, 0x02, 0x29, + + 0x1f, 0x60, 0x2f, 0x21, 0x42, 0x4f, 0x4f, 0x54, + 0x0d, 0xad, 0x87, 0x02, 0x49, 0x4c, 0xd0, 0x13, + + 0x4c, 0x87, 0x02, 0xad, 0x90, 0x02, 0x8e, 0x90, + 0x02, 0xaa, 0x98, 0x29, 0x01, 0xac, 0x91, 0x02, + + 0x8d, 0x91, 0x02, 0x60, 0x98, 0x9d, 0x00, 0xfc, + 0x60, 0x98, 0x9d, 0x00, 0xfd, 0x60, 0x98, 0x9d, + + 0x00, 0xfe, 0x60, 0xa9, 0x04, 0x9d, 0x08, 0x08, + 0xa9, 0xc0, 0x9d, 0x04, 0x08, 0xac, 0x62, 0x02, + + 0xf0, 0x02, 0xa9, 0xc0, 0x38, 0xe9, 0x40, 0x4a, + 0x4a, 0x4a, 0x49, 0x0f, 0x1d, 0x3c, 0xeb, 0x09, + + 0x10, 0x08, 0x78, 0xa0, 0xff, 0x8c, 0x43, 0xfe, + 0x8d, 0x4f, 0xfe, 0xc8, 0x8c, 0x40, 0xfe, 0xa0, + + 0x02, 0x88, 0xd0, 0xfd, 0xa0, 0x08, 0x8c, 0x40, + 0xfe, 0xa0, 0x04, 0x88, 0xd0, 0xfd, 0x28, 0x60, + + 0xe0, 0xc0, 0xa0, 0x80, 0x4c, 0x59, 0xec, 0xa9, + 0x00, 0x8d, 0x3b, 0x08, 0xad, 0x38, 0x08, 0xd0, + + 0x06, 0xee, 0x3b, 0x08, 0xce, 0x38, 0x08, 0xa2, + 0x08, 0xca, 0xbd, 0x00, 0x08, 0xf0, 0xe5, 0xbd, + + 0xcf, 0x02, 0x30, 0x05, 0xbd, 0x18, 0x08, 0xd0, + 0x03, 0x20, 0x6b, 0xec, 0xbd, 0x18, 0x08, 0xf0, + + 0x13, 0xc9, 0xff, 0xf0, 0x12, 0xde, 0x1c, 0x08, + 0xd0, 0x0d, 0xa9, 0x05, 0x9d, 0x1c, 0x08, 0xde, + + 0x18, 0x08, 0xd0, 0x03, 0x20, 0x6b, 0xec, 0xbd, + 0x24, 0x08, 0xf0, 0x05, 0xde, 0x24, 0x08, 0xd0, + + 0xb3, 0xbc, 0x20, 0x08, 0xc0, 0xff, 0xf0, 0xac, + 0xb9, 0xc0, 0x08, 0x29, 0x7f, 0x9d, 0x24, 0x08, + + 0xbd, 0x08, 0x08, 0xc9, 0x04, 0xf0, 0x60, 0xbd, + 0x08, 0x08, 0x18, 0x7d, 0x20, 0x08, 0xa8, 0xb9, + + 0xcb, 0x08, 0x38, 0xe9, 0x3f, 0x8d, 0x3a, 0x08, + 0xb9, 0xc7, 0x08, 0x8d, 0x39, 0x08, 0xbd, 0x04, + + 0x08, 0x48, 0x18, 0x6d, 0x39, 0x08, 0x50, 0x07, + 0x2a, 0xa9, 0x3f, 0xb0, 0x02, 0x49, 0xff, 0x9d, + + 0x04, 0x08, 0x2a, 0x5d, 0x04, 0x08, 0x10, 0x09, + 0xa9, 0x3f, 0x90, 0x02, 0x49, 0xff, 0x9d, 0x04, + + 0x08, 0xce, 0x39, 0x08, 0xbd, 0x04, 0x08, 0x38, + 0xed, 0x3a, 0x08, 0x4d, 0x39, 0x08, 0x30, 0x09, + + 0xad, 0x3a, 0x08, 0x9d, 0x04, 0x08, 0xfe, 0x08, + 0x08, 0x68, 0x5d, 0x04, 0x08, 0x29, 0xf8, 0xf0, + + 0x06, 0xbd, 0x04, 0x08, 0x20, 0x0a, 0xeb, 0xbd, + 0x10, 0x08, 0xc9, 0x03, 0xf0, 0x4b, 0xbd, 0x14, + + 0x08, 0xd0, 0x2a, 0xfe, 0x10, 0x08, 0xbd, 0x10, + 0x08, 0xc9, 0x03, 0xd0, 0x10, 0xbc, 0x20, 0x08, + + 0xb9, 0xc0, 0x08, 0x30, 0x34, 0xa9, 0x00, 0x9d, + 0x30, 0x08, 0x9d, 0x10, 0x08, 0xbd, 0x10, 0x08, + + 0x18, 0x7d, 0x20, 0x08, 0xa8, 0xb9, 0xc4, 0x08, + 0x9d, 0x14, 0x08, 0xf0, 0x1c, 0xde, 0x14, 0x08, + + 0xbd, 0x20, 0x08, 0x18, 0x7d, 0x10, 0x08, 0xa8, + 0xb9, 0xc1, 0x08, 0x18, 0x7d, 0x30, 0x08, 0x9d, + + 0x30, 0x08, 0x18, 0x7d, 0x0c, 0x08, 0x20, 0x01, + 0xed, 0xe0, 0x04, 0xf0, 0x0d, 0x4c, 0x59, 0xeb, + + 0xa2, 0x08, 0xca, 0x20, 0xa2, 0xec, 0xe0, 0x04, + 0xd0, 0xf8, 0x60, 0xbd, 0x08, 0x08, 0xc9, 0x04, + + 0xf0, 0x05, 0xa9, 0x03, 0x9d, 0x08, 0x08, 0xbd, + 0xcf, 0x02, 0xf0, 0x14, 0xa9, 0x00, 0x9d, 0xcf, + + 0x02, 0xa0, 0x04, 0x99, 0x2b, 0x08, 0x88, 0xd0, + 0xfa, 0x9d, 0x18, 0x08, 0x88, 0x8c, 0x38, 0x08, + + 0xbd, 0x28, 0x08, 0xf0, 0x46, 0xad, 0x3b, 0x08, + 0xf0, 0x36, 0xa9, 0x00, 0x9d, 0x28, 0x08, 0x4c, + + 0x98, 0xed, 0x20, 0x03, 0xeb, 0x98, 0x9d, 0x18, + 0x08, 0x9d, 0xcf, 0x02, 0x9d, 0x00, 0x08, 0xa0, + + 0x03, 0x99, 0x2c, 0x08, 0x88, 0x10, 0xfa, 0x8c, + 0x38, 0x08, 0x30, 0x4a, 0x08, 0x78, 0xbd, 0x08, + + 0x08, 0xc9, 0x04, 0xd0, 0x0a, 0x20, 0x5b, 0xe4, + 0x90, 0x05, 0xa9, 0x00, 0x9d, 0x00, 0x08, 0x28, + + 0xbc, 0x20, 0x08, 0xc0, 0xff, 0xd0, 0x03, 0x20, + 0x03, 0xeb, 0x60, 0x20, 0x5b, 0xe4, 0xb0, 0xdc, + + 0x29, 0x03, 0xf0, 0xbb, 0xad, 0x38, 0x08, 0xf0, + 0x15, 0xfe, 0x28, 0x08, 0x2c, 0x38, 0x08, 0x10, + + 0x0a, 0x20, 0x5b, 0xe4, 0x29, 0x03, 0x8d, 0x38, + 0x08, 0x10, 0x03, 0xce, 0x38, 0x08, 0x4c, 0xd0, + + 0xec, 0xdd, 0x2c, 0x08, 0xf0, 0xd4, 0x9d, 0x2c, + 0x08, 0xe0, 0x04, 0xd0, 0x09, 0x29, 0x0f, 0x1d, + + 0x3c, 0xeb, 0x08, 0x4c, 0x95, 0xed, 0x48, 0x29, + 0x03, 0x8d, 0x3c, 0x08, 0xa9, 0x00, 0x8d, 0x3d, + + 0x08, 0x68, 0x4a, 0x4a, 0xc9, 0x0c, 0x90, 0x07, + 0xee, 0x3d, 0x08, 0xe9, 0x0c, 0xd0, 0xf5, 0xa8, + + 0xad, 0x3d, 0x08, 0x48, 0xb9, 0xfb, 0xed, 0x8d, + 0x3d, 0x08, 0xb9, 0x07, 0xee, 0x48, 0x29, 0x03, + + 0x8d, 0x3e, 0x08, 0x68, 0x4a, 0x4a, 0x4a, 0x4a, + 0x8d, 0x3f, 0x08, 0xad, 0x3d, 0x08, 0xac, 0x3c, + + 0x08, 0xf0, 0x0c, 0x38, 0xed, 0x3f, 0x08, 0xb0, + 0x03, 0xce, 0x3e, 0x08, 0x88, 0xd0, 0xf4, 0x8d, + + 0x3d, 0x08, 0x68, 0xa8, 0xf0, 0x09, 0x4e, 0x3e, + 0x08, 0x6e, 0x3d, 0x08, 0x88, 0xd0, 0xf7, 0xad, + + 0x3d, 0x08, 0x18, 0x7d, 0x3d, 0xc4, 0x8d, 0x3d, + 0x08, 0x90, 0x03, 0xee, 0x3e, 0x08, 0x29, 0x0f, + + 0x1d, 0x3c, 0xeb, 0x08, 0x78, 0x20, 0x21, 0xeb, + 0xad, 0x3d, 0x08, 0x4e, 0x3e, 0x08, 0x6a, 0x4e, + + 0x3e, 0x08, 0x6a, 0x4a, 0x4a, 0x4c, 0x22, 0xeb, + 0x08, 0x78, 0x20, 0x60, 0xe4, 0x48, 0x29, 0x04, + + 0xf0, 0x15, 0x68, 0xbc, 0x20, 0x08, 0xc0, 0xff, + 0xd0, 0x03, 0x20, 0x03, 0xeb, 0x20, 0x60, 0xe4, + + 0x20, 0x60, 0xe4, 0x28, 0x4c, 0xf7, 0xed, 0x68, + 0x29, 0xf8, 0x0a, 0x90, 0x0b, 0x49, 0xff, 0x4a, + + 0x38, 0xe9, 0x40, 0x20, 0x0a, 0xeb, 0xa9, 0xff, + 0x9d, 0x20, 0x08, 0xa9, 0x05, 0x9d, 0x1c, 0x08, + + 0xa9, 0x01, 0x9d, 0x24, 0x08, 0xa9, 0x00, 0x9d, + 0x14, 0x08, 0x9d, 0x08, 0x08, 0x9d, 0x30, 0x08, + + 0xa9, 0xff, 0x9d, 0x10, 0x08, 0x20, 0x60, 0xe4, + 0x9d, 0x0c, 0x08, 0x20, 0x60, 0xe4, 0x28, 0x48, + + 0xbd, 0x0c, 0x08, 0x20, 0x01, 0xed, 0x68, 0x9d, + 0x18, 0x08, 0x60, 0xf0, 0xb7, 0x82, 0x4f, 0x20, + + 0xf3, 0xc8, 0xa0, 0x7b, 0x57, 0x35, 0x16, 0xe7, + 0xd7, 0xcb, 0xc3, 0xb7, 0xaa, 0xa2, 0x9a, 0x92, + + 0x8a, 0x82, 0x7a, 0xa9, 0xef, 0x85, 0xf5, 0x60, + 0xa2, 0x0d, 0xe6, 0xf5, 0xa4, 0xf5, 0x10, 0x39, + + 0xa2, 0x00, 0x86, 0xf7, 0xe8, 0x86, 0xf6, 0x20, + 0xbb, 0xee, 0xa2, 0x03, 0x20, 0x62, 0xee, 0xdd, + + 0x0c, 0xdf, 0xd0, 0xe4, 0xca, 0x10, 0xf5, 0xa9, + 0x3e, 0x85, 0xf6, 0x20, 0xbb, 0xee, 0xa2, 0xff, + + 0x20, 0x62, 0xee, 0xa0, 0x08, 0x0a, 0x76, 0xf7, + 0x88, 0xd0, 0xfa, 0xe8, 0xf0, 0xf2, 0x18, 0x90, + + 0x6a, 0xa2, 0x0e, 0xa4, 0xf5, 0x30, 0x0b, 0xa0, + 0xff, 0x08, 0x20, 0x68, 0xf1, 0x28, 0xc9, 0x01, + + 0x98, 0x60, 0x08, 0x78, 0xa0, 0x10, 0x20, 0x7f, + 0xee, 0xa0, 0x00, 0xf0, 0x17, 0xa0, 0x00, 0xf0, + + 0x11, 0x48, 0x20, 0x7a, 0xee, 0x68, 0x6a, 0x6a, + 0x6a, 0x6a, 0x29, 0x0f, 0x09, 0x40, 0xa8, 0x98, + + 0xa0, 0x01, 0x08, 0x78, 0x2c, 0x7b, 0x02, 0x10, + 0x21, 0x48, 0xb9, 0x75, 0xf0, 0x8d, 0x43, 0xfe, + + 0x68, 0x8d, 0x4f, 0xfe, 0xb9, 0x77, 0xf0, 0x8d, + 0x40, 0xfe, 0x2c, 0x40, 0xfe, 0x30, 0xfb, 0xad, + + 0x4f, 0xfe, 0x48, 0xb9, 0x79, 0xf0, 0x8d, 0x40, + 0xfe, 0x68, 0x28, 0xa8, 0x60, 0xad, 0xcb, 0x03, + + 0x85, 0xf6, 0xad, 0xcc, 0x03, 0x85, 0xf7, 0xa5, + 0xf5, 0x10, 0x1e, 0x08, 0x78, 0xa5, 0xf6, 0x20, + + 0x71, 0xee, 0xa5, 0xf5, 0x85, 0xfa, 0xa5, 0xf7, + 0x2a, 0x2a, 0x46, 0xfa, 0x6a, 0x46, 0xfa, 0x6a, + + 0x20, 0x71, 0xee, 0xa5, 0xfa, 0x20, 0x7a, 0xee, + 0x28, 0x60, 0xa2, 0xff, 0xa5, 0xec, 0x05, 0xed, + + 0xd0, 0x06, 0xa9, 0x81, 0x8d, 0x4e, 0xfe, 0xe8, + 0x8e, 0x42, 0x02, 0x08, 0xad, 0x5a, 0x02, 0x4a, + + 0x29, 0x18, 0x09, 0x06, 0x8d, 0x40, 0xfe, 0x4a, + 0x09, 0x07, 0x8d, 0x40, 0xfe, 0x20, 0x2e, 0xf1, + + 0x68, 0x60, 0x50, 0x0a, 0xa9, 0x01, 0x8d, 0x4e, + 0xfe, 0xb0, 0x08, 0x4c, 0x0f, 0xf0, 0x90, 0x06, + + 0x4c, 0xd1, 0xf0, 0xee, 0x42, 0x02, 0xad, 0x5a, + 0x02, 0x29, 0xb7, 0xa2, 0x00, 0x20, 0x2a, 0xf0, + + 0x86, 0xfa, 0xb8, 0x10, 0x05, 0x2c, 0xb7, 0xd9, + 0x09, 0x08, 0xe8, 0x20, 0x2a, 0xf0, 0x90, 0xbb, + + 0x10, 0x02, 0x09, 0x40, 0x8d, 0x5a, 0x02, 0xa6, + 0xec, 0xf0, 0x12, 0x20, 0x2a, 0xf0, 0x30, 0x10, + + 0xe4, 0xec, 0x86, 0xec, 0xd0, 0x07, 0xa2, 0x00, + 0x86, 0xec, 0x20, 0x1f, 0xf0, 0x4c, 0xe9, 0xef, + + 0xe4, 0xec, 0xd0, 0xee, 0xa5, 0xe7, 0xf0, 0x23, + 0xc6, 0xe7, 0xd0, 0x1f, 0xad, 0xca, 0x02, 0x85, + + 0xe7, 0xad, 0x55, 0x02, 0x8d, 0xca, 0x02, 0xad, + 0x5a, 0x02, 0xa6, 0xec, 0xe0, 0xd0, 0xd0, 0x0e, + + 0x09, 0x90, 0x49, 0xa0, 0x8d, 0x5a, 0x02, 0xa9, + 0x00, 0x85, 0xe7, 0x4c, 0xe9, 0xef, 0xe0, 0xc0, + + 0xd0, 0x0f, 0x09, 0xa0, 0x24, 0xfa, 0x10, 0x04, + 0x09, 0x10, 0x49, 0x80, 0x49, 0x90, 0x4c, 0x74, + + 0xef, 0xbd, 0xab, 0xef, 0xd0, 0x03, 0xad, 0x6b, + 0x02, 0xae, 0x5a, 0x02, 0x86, 0xfa, 0x26, 0xfa, + + 0x10, 0x07, 0xa6, 0xed, 0xd0, 0xa4, 0x20, 0xbf, + 0xea, 0x26, 0xfa, 0x30, 0x08, 0x20, 0x9c, 0xea, + + 0x26, 0xfa, 0x4c, 0xc1, 0xef, 0x26, 0xfa, 0x30, + 0x0d, 0x20, 0xe3, 0xe4, 0xb0, 0x08, 0x20, 0x9c, + + 0xea, 0xae, 0x5a, 0x02, 0x10, 0x0b, 0x26, 0xfa, + 0x10, 0x07, 0xa6, 0xed, 0xd0, 0xd6, 0x20, 0x9c, + + 0xea, 0xcd, 0x6c, 0x02, 0xd0, 0x07, 0xae, 0x75, + 0x02, 0xd0, 0x02, 0x86, 0xe7, 0xa8, 0x20, 0x29, + + 0xf1, 0xad, 0x59, 0x02, 0xd0, 0x03, 0x20, 0xf1, + 0xe4, 0xa6, 0xed, 0xf0, 0x0b, 0x20, 0x2a, 0xf0, + + 0x86, 0xed, 0x30, 0x04, 0xa2, 0x00, 0x86, 0xed, + 0xa6, 0xed, 0xd0, 0x16, 0xa0, 0xec, 0x20, 0xcc, + + 0xf0, 0x30, 0x09, 0xa5, 0xec, 0x85, 0xed, 0x86, + 0xec, 0x20, 0x1f, 0xf0, 0x4c, 0xda, 0xee, 0x20, + + 0x2a, 0xf0, 0xa5, 0xec, 0xd0, 0xf6, 0xa0, 0xed, + 0x20, 0xcc, 0xf0, 0x30, 0xef, 0x10, 0xe8, 0xa2, + + 0x01, 0x86, 0xe7, 0xae, 0x54, 0x02, 0x8e, 0xca, + 0x02, 0x60, 0xa0, 0x03, 0x8c, 0x40, 0xfe, 0xa0, + + 0x7f, 0x8c, 0x43, 0xfe, 0x8e, 0x4f, 0xfe, 0xae, + 0x4f, 0xfe, 0x60, 0x71, 0x33, 0x34, 0x35, 0x84, + + 0x38, 0x87, 0x2d, 0x5e, 0x8c, 0x84, 0xec, 0x86, + 0xed, 0x60, 0x00, 0x80, 0x77, 0x65, 0x74, 0x37, + + 0x69, 0x39, 0x30, 0x5f, 0x8e, 0x6c, 0xfe, 0xfd, + 0x6c, 0xfa, 0x00, 0x31, 0x32, 0x64, 0x72, 0x36, + + 0x75, 0x6f, 0x70, 0x5b, 0x8f, 0x2c, 0xb7, 0xd9, + 0x6c, 0x28, 0x02, 0x01, 0x61, 0x78, 0x66, 0x79, + + 0x6a, 0x6b, 0x40, 0x3a, 0x0d, 0x00, 0xff, 0x01, + 0x02, 0x09, 0x0a, 0x02, 0x73, 0x63, 0x67, 0x68, + + 0x6e, 0x6c, 0x3b, 0x5d, 0x7f, 0xac, 0x44, 0x02, + 0xa2, 0x00, 0x60, 0x00, 0x7a, 0x20, 0x76, 0x62, + + 0x6d, 0x2c, 0x2e, 0x2f, 0x8b, 0xae, 0x41, 0x02, + 0x4c, 0xad, 0xe1, 0x1b, 0x81, 0x82, 0x83, 0x85, + + 0x86, 0x88, 0x89, 0x5c, 0x8d, 0x6c, 0x20, 0x02, + 0xd0, 0xeb, 0xa2, 0x08, 0x58, 0x78, 0x20, 0xb4, + + 0xf0, 0xca, 0x10, 0xf8, 0xe0, 0x09, 0x90, 0xe0, + 0x60, 0xa2, 0x09, 0x20, 0x68, 0xf1, 0x20, 0x4a, + + 0xfa, 0x0d, 0x4f, 0x53, 0x20, 0x31, 0x2e, 0x32, + 0x30, 0x0d, 0x00, 0x60, 0x18, 0xa2, 0x10, 0xb0, + + 0x97, 0x8a, 0x10, 0x05, 0x20, 0x2a, 0xf0, 0xb0, + 0x55, 0x08, 0x90, 0x02, 0xa0, 0xee, 0x99, 0xdf, + + 0x01, 0xa2, 0x09, 0x20, 0x29, 0xf1, 0xa9, 0x7f, + 0x8d, 0x43, 0xfe, 0xa9, 0x03, 0x8d, 0x40, 0xfe, + + 0xa9, 0x0f, 0x8d, 0x4f, 0xfe, 0xa9, 0x01, 0x8d, + 0x4d, 0xfe, 0x8e, 0x4f, 0xfe, 0x2c, 0x4d, 0xfe, + + 0xf0, 0x21, 0x8a, 0xd9, 0xdf, 0x01, 0x90, 0x16, + 0x8d, 0x4f, 0xfe, 0x2c, 0x4f, 0xfe, 0x10, 0x0e, + + 0x28, 0x08, 0xb0, 0x13, 0x48, 0x59, 0x00, 0x00, + 0x0a, 0xc9, 0x01, 0x68, 0xb0, 0x09, 0x18, 0x69, + + 0x10, 0x10, 0xe0, 0xca, 0x10, 0xbd, 0x8a, 0xaa, + 0x28, 0x20, 0x2e, 0xf1, 0x58, 0x78, 0xa9, 0x0b, + + 0x8d, 0x40, 0xfe, 0x8a, 0x60, 0x49, 0x8c, 0x0a, + 0x8d, 0x47, 0x02, 0xe0, 0x03, 0x4c, 0x4b, 0xf1, + + 0x08, 0xa9, 0xa1, 0x85, 0xe3, 0xa9, 0x19, 0x8d, + 0xd1, 0x03, 0x28, 0x08, 0xa9, 0x06, 0x20, 0x31, + + 0xe0, 0xa2, 0x06, 0x28, 0xf0, 0x01, 0xca, 0x86, + 0xc6, 0xa2, 0x0e, 0xbd, 0x51, 0xd9, 0x9d, 0x11, + + 0x02, 0xca, 0xd0, 0xf7, 0x86, 0xc2, 0xa2, 0x0f, + 0xa5, 0xf4, 0x48, 0x8a, 0xa2, 0x0f, 0xfe, 0xa1, + + 0x02, 0xde, 0xa1, 0x02, 0x10, 0x0d, 0x86, 0xf4, + 0x8e, 0x30, 0xfe, 0x20, 0x03, 0x80, 0xaa, 0xf0, + + 0x05, 0xa6, 0xf4, 0xca, 0x10, 0xe8, 0x68, 0x85, + 0xf4, 0x8d, 0x30, 0xfe, 0x8a, 0x60, 0x09, 0x00, + + 0xd0, 0x10, 0xc0, 0x00, 0xd0, 0x0c, 0xa5, 0xc6, + 0x29, 0xfb, 0x0d, 0x47, 0x02, 0x0a, 0x0d, 0x47, + + 0x02, 0x4a, 0x60, 0x4c, 0xf5, 0x1d, 0xf6, 0x04, + 0xf3, 0x0f, 0xe3, 0x04, 0xf3, 0x2a, 0xf3, 0x74, + + 0xe2, 0xc9, 0x07, 0xb0, 0xed, 0x86, 0xbc, 0x0a, + 0xaa, 0xbd, 0xa4, 0xf1, 0x48, 0xbd, 0xa3, 0xf1, + + 0x48, 0xa6, 0xbc, 0x60, 0x08, 0x48, 0x20, 0x27, + 0xfb, 0xad, 0xc2, 0x03, 0x48, 0x20, 0x31, 0xf6, + + 0x68, 0xf0, 0x1a, 0xa2, 0x03, 0xa9, 0xff, 0x48, + 0xbd, 0xbe, 0x03, 0x95, 0xb0, 0x68, 0x35, 0xb0, + + 0xca, 0x10, 0xf4, 0xc9, 0xff, 0xd0, 0x06, 0x20, + 0xe8, 0xfa, 0x4c, 0x67, 0xe2, 0xad, 0xca, 0x03, + + 0x4a, 0x68, 0xf0, 0x0e, 0x90, 0x13, 0x20, 0xf2, + 0xfa, 0x00, 0xd5, 0x4c, 0x6f, 0x63, 0x6b, 0x65, + + 0x64, 0x00, 0x90, 0x05, 0xa9, 0x03, 0x8d, 0x58, + 0x02, 0xa9, 0x30, 0x25, 0xbb, 0xf0, 0x04, 0xa5, + + 0xc1, 0xd0, 0x0a, 0x98, 0x48, 0x20, 0xbb, 0xfb, + 0x68, 0xa8, 0x20, 0xd5, 0xf7, 0x20, 0xb4, 0xf9, + + 0xd0, 0x33, 0x20, 0x69, 0xfb, 0x2c, 0xca, 0x03, + 0x30, 0x08, 0x20, 0x6a, 0xf9, 0x20, 0x7b, 0xf7, + + 0xd0, 0xd7, 0xa0, 0x0a, 0xa5, 0xcc, 0x91, 0xc8, + 0xc8, 0xa5, 0xcd, 0x91, 0xc8, 0xa9, 0x00, 0xc8, + + 0x91, 0xc8, 0xc8, 0x91, 0xc8, 0x28, 0x20, 0xe8, + 0xfa, 0x24, 0xba, 0x30, 0x07, 0x08, 0x20, 0x46, + + 0xfa, 0x0d, 0x00, 0x28, 0x60, 0x20, 0x37, 0xf6, + 0xd0, 0xaf, 0x86, 0xf2, 0x84, 0xf3, 0xa0, 0x00, + + 0x20, 0x1d, 0xea, 0xa2, 0x00, 0x20, 0x2f, 0xea, + 0xb0, 0x0d, 0xf0, 0x08, 0x9d, 0xd2, 0x03, 0xe8, + + 0xe0, 0x0b, 0xd0, 0xf1, 0x4c, 0x8f, 0xea, 0xa9, + 0x00, 0x9d, 0xd2, 0x03, 0x60, 0x48, 0x86, 0xc8, + + 0x84, 0xc9, 0xa0, 0x00, 0xb1, 0xc8, 0xaa, 0xc8, + 0xb1, 0xc8, 0xa8, 0x20, 0x5a, 0xf2, 0xa0, 0x02, + + 0xb1, 0xc8, 0x99, 0xbc, 0x03, 0x99, 0xae, 0x00, + 0xc8, 0xc0, 0x0a, 0xd0, 0xf3, 0x68, 0xf0, 0x07, + + 0xc9, 0xff, 0xd0, 0xb0, 0x4c, 0xc4, 0xf1, 0x8d, + 0xc6, 0x03, 0x8d, 0xc7, 0x03, 0xb1, 0xc8, 0x99, + + 0xa6, 0x00, 0xc8, 0xc0, 0x12, 0xd0, 0xf6, 0x8a, + 0xf0, 0xba, 0x20, 0x27, 0xfb, 0x20, 0x34, 0xf9, + + 0xa9, 0x00, 0x20, 0xbd, 0xfb, 0x20, 0xe2, 0xfb, + 0x38, 0xa2, 0xfd, 0xbd, 0xb7, 0xff, 0xfd, 0xb3, + + 0xff, 0x9d, 0xcb, 0x02, 0xe8, 0xd0, 0xf4, 0xa8, + 0xd0, 0x0e, 0xec, 0xc8, 0x03, 0xa9, 0x01, 0xed, + + 0xc9, 0x03, 0x90, 0x04, 0xa2, 0x80, 0xd0, 0x08, + 0xa9, 0x01, 0x8d, 0xc9, 0x03, 0x8e, 0xc8, 0x03, + + 0x8e, 0xca, 0x03, 0x20, 0xec, 0xf7, 0x30, 0x49, + 0x20, 0x6a, 0xf9, 0xee, 0xc6, 0x03, 0xd0, 0xc8, + + 0xee, 0xc7, 0x03, 0xd0, 0xc3, 0x20, 0x5a, 0xf2, + 0xa2, 0xff, 0x8e, 0xc2, 0x03, 0x20, 0xc4, 0xf1, + + 0x2c, 0x7a, 0x02, 0x10, 0x0a, 0xad, 0xc4, 0x03, + 0x2d, 0xc5, 0x03, 0xc9, 0xff, 0xd0, 0x03, 0x6c, + + 0xc2, 0x03, 0xa2, 0xc2, 0xa0, 0x03, 0xa9, 0x04, + 0x4c, 0xc7, 0xfb, 0xa9, 0x08, 0x20, 0x44, 0xf3, + + 0x20, 0x27, 0xfb, 0xa9, 0x00, 0x20, 0x48, 0xf3, + 0x20, 0xfc, 0xfa, 0xa9, 0xf7, 0x25, 0xe2, 0x85, + + 0xe2, 0x60, 0xa9, 0x40, 0x05, 0xe2, 0xd0, 0xf7, + 0x48, 0xad, 0x47, 0x02, 0xf0, 0x0b, 0x20, 0x13, + + 0xee, 0x20, 0x18, 0xee, 0x90, 0x03, 0xb8, 0x50, + 0x41, 0x20, 0x7b, 0xf7, 0xad, 0xc6, 0x03, 0x85, + + 0xb4, 0xad, 0xc7, 0x03, 0x85, 0xb5, 0xa2, 0xff, + 0x8e, 0xdf, 0x03, 0xe8, 0x86, 0xba, 0xf0, 0x06, + + 0x20, 0x69, 0xfb, 0x20, 0x7b, 0xf7, 0xad, 0x47, + 0x02, 0xf0, 0x02, 0x50, 0x1d, 0x68, 0x48, 0xf0, + + 0x2d, 0x20, 0x72, 0xfa, 0xd0, 0x16, 0xa9, 0x30, + 0x25, 0xbb, 0xf0, 0x0e, 0xad, 0xc6, 0x03, 0xc5, + + 0xb6, 0xd0, 0x09, 0xad, 0xc7, 0x03, 0xc5, 0xb7, + 0xd0, 0x02, 0x68, 0x60, 0xad, 0x47, 0x02, 0xf0, + + 0x0d, 0x20, 0xad, 0xee, 0xa9, 0xff, 0x8d, 0xc6, + 0x03, 0x8d, 0xc7, 0x03, 0xd0, 0xc2, 0x50, 0x05, + + 0xa9, 0xff, 0x20, 0xd7, 0xf7, 0xa2, 0x00, 0x20, + 0xd9, 0xf9, 0xad, 0x47, 0x02, 0xf0, 0x04, 0x24, + + 0xbb, 0x50, 0xde, 0x2c, 0xca, 0x03, 0x30, 0xdc, + 0x10, 0xa6, 0x85, 0xbc, 0x8a, 0x48, 0x98, 0x48, + + 0xa5, 0xbc, 0xd0, 0x1e, 0x98, 0xd0, 0x0c, 0x20, + 0x75, 0xe2, 0x20, 0x78, 0xf4, 0x46, 0xe2, 0x06, + + 0xe2, 0x90, 0x0c, 0x4a, 0xb0, 0xf7, 0x4a, 0xb0, + 0x03, 0x4c, 0xb1, 0xfb, 0x20, 0x78, 0xf4, 0x4c, + + 0x71, 0xf4, 0x20, 0x5a, 0xf2, 0x24, 0xbc, 0x50, + 0x3d, 0xa9, 0x00, 0x8d, 0x9e, 0x03, 0x8d, 0xdd, + + 0x03, 0x8d, 0xde, 0x03, 0xa9, 0x3e, 0x20, 0x3d, + 0xf3, 0x20, 0x1a, 0xfb, 0x08, 0x20, 0x31, 0xf6, + + 0x20, 0xb4, 0xf6, 0x28, 0xa2, 0xff, 0xe8, 0xbd, + 0xb2, 0x03, 0x9d, 0xa7, 0x03, 0xd0, 0xf7, 0xa9, + + 0x01, 0x20, 0x44, 0xf3, 0xad, 0xea, 0x02, 0x0d, + 0xeb, 0x02, 0xd0, 0x03, 0x20, 0x42, 0xf3, 0xa9, + + 0x01, 0x0d, 0x47, 0x02, 0xd0, 0x39, 0x8a, 0xd0, + 0x03, 0x4c, 0x8f, 0xea, 0xa2, 0xff, 0xe8, 0xbd, + + 0xd2, 0x03, 0x9d, 0x80, 0x03, 0xd0, 0xf7, 0xa9, + 0xff, 0xa2, 0x08, 0x9d, 0x8b, 0x03, 0xca, 0xd0, + + 0xfa, 0x8a, 0xa2, 0x14, 0x9d, 0x80, 0x03, 0xe8, + 0xe0, 0x1e, 0xd0, 0xf8, 0x2e, 0x97, 0x03, 0x20, + + 0x27, 0xfb, 0x20, 0x34, 0xf9, 0x20, 0xf2, 0xfa, + 0xa9, 0x02, 0x20, 0x44, 0xf3, 0xa9, 0x02, 0x85, + + 0xbc, 0x68, 0xa8, 0x68, 0xaa, 0xa5, 0xbc, 0x60, + 0xa9, 0x02, 0x25, 0xe2, 0xf0, 0xf9, 0xa9, 0x00, + + 0x8d, 0x97, 0x03, 0xa9, 0x80, 0xae, 0x9d, 0x03, + 0x8e, 0x96, 0x03, 0x8d, 0x98, 0x03, 0x20, 0x96, + + 0xf4, 0xa9, 0xfd, 0x4c, 0x3d, 0xf3, 0x20, 0x1a, + 0xfb, 0xa2, 0x11, 0xbd, 0x8c, 0x03, 0x9d, 0xbe, + + 0x03, 0xca, 0x10, 0xf7, 0x86, 0xb2, 0x86, 0xb3, + 0xe8, 0x86, 0xb0, 0xa9, 0x09, 0x85, 0xb1, 0xa2, + + 0x7f, 0x20, 0x81, 0xfb, 0x8d, 0xdf, 0x03, 0x20, + 0x8e, 0xfb, 0x20, 0xe2, 0xfb, 0x20, 0xec, 0xf7, + + 0xee, 0x94, 0x03, 0xd0, 0x03, 0xee, 0x95, 0x03, + 0x60, 0x8a, 0x48, 0x98, 0x48, 0xa9, 0x01, 0x20, + + 0x9c, 0xfb, 0xa5, 0xe2, 0x0a, 0xb0, 0x4c, 0x0a, + 0x90, 0x09, 0xa9, 0x80, 0x20, 0x44, 0xf3, 0xa9, + + 0xfe, 0xb0, 0x38, 0xae, 0x9e, 0x03, 0xe8, 0xec, + 0xea, 0x02, 0xd0, 0x2a, 0x2c, 0xec, 0x02, 0x30, + + 0x22, 0xad, 0xed, 0x02, 0x48, 0x20, 0x1a, 0xfb, + 0x08, 0x20, 0xac, 0xf6, 0x28, 0x68, 0x85, 0xbc, + + 0x18, 0x2c, 0xec, 0x02, 0x10, 0x17, 0xad, 0xea, + 0x02, 0x0d, 0xeb, 0x02, 0xd0, 0x0f, 0x20, 0x42, + + 0xf3, 0xd0, 0x0a, 0x20, 0x42, 0xf3, 0xca, 0x18, + 0xbd, 0x00, 0x0a, 0x85, 0xbc, 0xee, 0x9e, 0x03, + + 0x4c, 0x71, 0xf4, 0x00, 0xdf, 0x45, 0x4f, 0x46, + 0x00, 0x85, 0xc4, 0x8a, 0x48, 0x98, 0x48, 0xa9, + + 0x02, 0x20, 0x9c, 0xfb, 0xae, 0x9d, 0x03, 0xa5, + 0xc4, 0x9d, 0x00, 0x09, 0xe8, 0xd0, 0x06, 0x20, + + 0x96, 0xf4, 0x20, 0xf2, 0xfa, 0xee, 0x9d, 0x03, + 0xa5, 0xc4, 0x4c, 0x6f, 0xf4, 0x8a, 0xf0, 0x2e, + + 0xe0, 0x03, 0xf0, 0x1f, 0xc0, 0x03, 0xb0, 0x06, + 0xca, 0xf0, 0x06, 0xca, 0xf0, 0x0a, 0x4c, 0x10, + + 0xe3, 0xa9, 0x33, 0xc8, 0xc8, 0xc8, 0xd0, 0x02, + 0xa9, 0xcc, 0xc8, 0x25, 0xe3, 0x19, 0x81, 0xf5, + + 0x85, 0xe3, 0x60, 0x98, 0x30, 0x02, 0xd0, 0x02, + 0xa9, 0x19, 0x8d, 0xd1, 0x03, 0x60, 0xa8, 0xf0, + + 0xec, 0xa1, 0x00, 0x22, 0x11, 0x00, 0x88, 0xcc, + 0xc6, 0xc0, 0xad, 0x47, 0x02, 0xf0, 0x07, 0x20, + + 0x51, 0xee, 0xa8, 0x18, 0x90, 0x1a, 0xad, 0x08, + 0xfe, 0x48, 0x29, 0x02, 0xf0, 0x0b, 0xa4, 0xca, + + 0xf0, 0x07, 0x68, 0xa5, 0xbd, 0x8d, 0x09, 0xfe, + 0x60, 0xac, 0x09, 0xfe, 0x68, 0x4a, 0x4a, 0x4a, + + 0xa6, 0xc2, 0xf0, 0x69, 0xca, 0xd0, 0x06, 0x90, + 0x64, 0xa0, 0x02, 0xd0, 0x5e, 0xca, 0xd0, 0x13, + + 0xb0, 0x5b, 0x98, 0x20, 0x78, 0xfb, 0xa0, 0x03, + 0xc9, 0x2a, 0xf0, 0x4f, 0x20, 0x50, 0xfb, 0xa0, + + 0x01, 0xd0, 0x48, 0xca, 0xd0, 0x0c, 0xb0, 0x04, + 0x84, 0xbd, 0xf0, 0x41, 0xa9, 0x80, 0x85, 0xc0, + + 0xd0, 0x3b, 0xca, 0xd0, 0x29, 0xb0, 0x2f, 0x98, + 0x20, 0xb0, 0xf7, 0xa4, 0xbc, 0xe6, 0xbc, 0x24, + + 0xbd, 0x30, 0x0d, 0x20, 0xd3, 0xfb, 0xf0, 0x05, + 0x8e, 0xe5, 0xfe, 0xd0, 0x03, 0x8a, 0x91, 0xb0, + + 0xc8, 0xcc, 0xc8, 0x03, 0xd0, 0x17, 0xa9, 0x01, + 0x85, 0xbc, 0xa0, 0x05, 0xd0, 0x0d, 0x98, 0x20, + + 0xb0, 0xf7, 0xc6, 0xbc, 0x10, 0x07, 0x20, 0x46, + 0xfb, 0xa0, 0x00, 0x84, 0xc2, 0x60, 0x48, 0x98, + + 0x48, 0x8a, 0xa8, 0xa9, 0x03, 0x20, 0x9c, 0xfb, + 0xa5, 0xe2, 0x29, 0x40, 0xaa, 0x68, 0xa8, 0x68, + + 0x60, 0xa9, 0x00, 0x85, 0xb4, 0x85, 0xb5, 0xa5, + 0xb4, 0x48, 0x85, 0xb6, 0xa5, 0xb5, 0x48, 0x85, + + 0xb7, 0x20, 0x46, 0xfa, 0x53, 0x65, 0x61, 0x72, + 0x63, 0x68, 0x69, 0x6e, 0x67, 0x0d, 0x00, 0xa9, + + 0xff, 0x20, 0x48, 0xf3, 0x68, 0x85, 0xb5, 0x68, + 0x85, 0xb4, 0xa5, 0xb6, 0x05, 0xb7, 0xd0, 0x0d, + + 0x85, 0xb4, 0x85, 0xb5, 0xa5, 0xc1, 0xd0, 0x05, + 0xa2, 0xb1, 0x20, 0x81, 0xfb, 0xad, 0x47, 0x02, + + 0xf0, 0x13, 0x70, 0x11, 0x00, 0xd6, 0x46, 0x69, + 0x6c, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x66, + + 0x6f, 0x75, 0x6e, 0x64, 0x00, 0xa0, 0xff, 0x8c, + 0xdf, 0x03, 0x60, 0xa9, 0x00, 0x08, 0x84, 0xe6, + + 0xac, 0x56, 0x02, 0x8d, 0x56, 0x02, 0xf0, 0x03, + 0x20, 0xce, 0xff, 0xa4, 0xe6, 0x28, 0xf0, 0x0b, + + 0xa9, 0x40, 0x20, 0xce, 0xff, 0xa8, 0xf0, 0xcc, + 0x8d, 0x56, 0x02, 0x60, 0xa2, 0xa6, 0x20, 0x81, + + 0xfb, 0x20, 0x7b, 0xf7, 0xad, 0xca, 0x03, 0x4a, + 0x90, 0x03, 0x4c, 0xf6, 0xf1, 0xad, 0xdd, 0x03, + + 0x85, 0xb4, 0xad, 0xde, 0x03, 0x85, 0xb5, 0xa9, + 0x00, 0x85, 0xb0, 0xa9, 0x0a, 0x85, 0xb1, 0xa9, + + 0xff, 0x85, 0xb2, 0x85, 0xb3, 0x20, 0xd5, 0xf7, + 0x20, 0xb4, 0xf9, 0xd0, 0x25, 0xad, 0xff, 0x0a, + + 0x8d, 0xed, 0x02, 0x20, 0x69, 0xfb, 0x8e, 0xdd, + 0x03, 0x8c, 0xde, 0x03, 0xa2, 0x02, 0xbd, 0xc8, + + 0x03, 0x9d, 0xea, 0x02, 0xca, 0x10, 0xf7, 0x2c, + 0xec, 0x02, 0x10, 0x03, 0x20, 0x49, 0xf2, 0x4c, + + 0xf2, 0xfa, 0x20, 0x37, 0xf6, 0xd0, 0xad, 0xc9, + 0x2a, 0xf0, 0x37, 0xc9, 0x23, 0xd0, 0x0f, 0xee, + + 0xc6, 0x03, 0xd0, 0x03, 0xee, 0xc7, 0x03, 0xa2, + 0xff, 0x2c, 0xb7, 0xd9, 0xd0, 0x55, 0xa9, 0xf7, + + 0x20, 0x3d, 0xf3, 0x00, 0xd7, 0x42, 0x61, 0x64, + 0x20, 0x52, 0x4f, 0x4d, 0x00, 0xa0, 0xff, 0x20, + + 0x90, 0xfb, 0xa9, 0x01, 0x85, 0xc2, 0x20, 0x50, + 0xfb, 0x20, 0x95, 0xf9, 0xa9, 0x03, 0xc5, 0xc2, + + 0xd0, 0xf7, 0xa0, 0x00, 0x20, 0x7c, 0xfb, 0x20, + 0x97, 0xf7, 0x50, 0x1a, 0x99, 0xb2, 0x03, 0xf0, + + 0x06, 0xc8, 0xc0, 0x0b, 0xd0, 0xf1, 0x88, 0xa2, + 0x0c, 0x20, 0x97, 0xf7, 0x50, 0x08, 0x9d, 0xb2, + + 0x03, 0xe8, 0xe0, 0x1f, 0xd0, 0xf3, 0x98, 0xaa, + 0xa9, 0x00, 0x99, 0xb2, 0x03, 0xa5, 0xbe, 0x05, + + 0xbf, 0x85, 0xc1, 0x20, 0x78, 0xfb, 0x84, 0xc2, + 0x8a, 0xd0, 0x59, 0xad, 0x47, 0x02, 0xf0, 0xad, + + 0x20, 0x51, 0xee, 0xc9, 0x2b, 0xd0, 0x80, 0xa9, + 0x08, 0x25, 0xe2, 0xf0, 0x03, 0x20, 0x4d, 0xf2, + + 0x20, 0x18, 0xee, 0x90, 0xeb, 0xb8, 0x60, 0xad, + 0x47, 0x02, 0xf0, 0x11, 0x8a, 0x48, 0x98, 0x48, + + 0x20, 0x51, 0xee, 0x85, 0xbd, 0xa9, 0xff, 0x85, + 0xc0, 0x68, 0xa8, 0x68, 0xaa, 0x20, 0x84, 0xf8, + + 0x08, 0x48, 0x38, 0x66, 0xcb, 0x45, 0xbf, 0x85, + 0xbf, 0xa5, 0xbf, 0x2a, 0x90, 0x0c, 0x6a, 0x49, + + 0x08, 0x85, 0xbf, 0xa5, 0xbe, 0x49, 0x10, 0x85, + 0xbe, 0x38, 0x26, 0xbe, 0x26, 0xbf, 0x46, 0xcb, + + 0xd0, 0xe7, 0x68, 0x28, 0x60, 0xa9, 0x00, 0x85, + 0xbd, 0xa2, 0x00, 0x86, 0xbc, 0x50, 0x0a, 0xad, + + 0xc8, 0x03, 0x0d, 0xc9, 0x03, 0xf0, 0x02, 0xa2, + 0x04, 0x86, 0xc2, 0x60, 0x08, 0xa2, 0x03, 0xa9, + + 0x00, 0x9d, 0xcb, 0x03, 0xca, 0x10, 0xfa, 0xad, + 0xc6, 0x03, 0x0d, 0xc7, 0x03, 0xd0, 0x05, 0x20, + + 0x92, 0xf8, 0xf0, 0x03, 0x20, 0x96, 0xf8, 0xa9, + 0x2a, 0x85, 0xbd, 0x20, 0x78, 0xfb, 0x20, 0x4a, + + 0xfb, 0x20, 0x84, 0xf8, 0x88, 0xc8, 0xb9, 0xd2, + 0x03, 0x99, 0xb2, 0x03, 0x20, 0x75, 0xf8, 0xd0, + + 0xf4, 0xa2, 0x0c, 0xbd, 0xb2, 0x03, 0x20, 0x75, + 0xf8, 0xe8, 0xe0, 0x1d, 0xd0, 0xf5, 0x20, 0x7b, + + 0xf8, 0xad, 0xc8, 0x03, 0x0d, 0xc9, 0x03, 0xf0, + 0x1c, 0xa0, 0x00, 0x20, 0x7c, 0xfb, 0xb1, 0xb0, + + 0x20, 0xd3, 0xfb, 0xf0, 0x03, 0xae, 0xe5, 0xfe, + 0x8a, 0x20, 0x75, 0xf8, 0xc8, 0xcc, 0xc8, 0x03, + + 0xd0, 0xec, 0x20, 0x7b, 0xf8, 0x20, 0x84, 0xf8, + 0x20, 0x84, 0xf8, 0x20, 0x46, 0xfb, 0xa9, 0x01, + + 0x20, 0x98, 0xf8, 0x28, 0x20, 0xb9, 0xf8, 0x2c, + 0xca, 0x03, 0x10, 0x08, 0x08, 0x20, 0x92, 0xf8, + + 0x20, 0x46, 0xf2, 0x28, 0x60, 0x20, 0x82, 0xf8, + 0x4c, 0xb0, 0xf7, 0xa5, 0xbf, 0x20, 0x82, 0xf8, + + 0xa5, 0xbe, 0x85, 0xbd, 0x20, 0x95, 0xf9, 0x24, + 0xc0, 0x10, 0xf9, 0xa9, 0x00, 0x85, 0xc0, 0xa5, + + 0xbd, 0x60, 0xa9, 0x32, 0xd0, 0x02, 0xa5, 0xc7, + 0xa2, 0x05, 0x8d, 0x40, 0x02, 0x20, 0x95, 0xf9, + + 0x2c, 0x40, 0x02, 0x10, 0xf8, 0xca, 0xd0, 0xf2, + 0x60, 0xad, 0xc6, 0x03, 0x0d, 0xc7, 0x03, 0xf0, + + 0x05, 0x2c, 0xdf, 0x03, 0x10, 0x03, 0x20, 0x49, + 0xf2, 0xa0, 0x00, 0x84, 0xba, 0xad, 0xca, 0x03, + + 0x8d, 0xdf, 0x03, 0x20, 0xdc, 0xe7, 0xf0, 0x6b, + 0xa9, 0x0d, 0x20, 0xee, 0xff, 0xb9, 0xb2, 0x03, + + 0xf0, 0x10, 0xc9, 0x20, 0x90, 0x04, 0xc9, 0x7f, + 0x90, 0x02, 0xa9, 0x3f, 0x20, 0xee, 0xff, 0xc8, + + 0xd0, 0xeb, 0xad, 0x47, 0x02, 0xf0, 0x04, 0x24, + 0xbb, 0x50, 0x48, 0x20, 0x91, 0xf9, 0xc8, 0xc0, + + 0x0b, 0x90, 0xef, 0xad, 0xc6, 0x03, 0xaa, 0x20, + 0x7a, 0xf9, 0x2c, 0xca, 0x03, 0x10, 0x34, 0x8a, + + 0x18, 0x6d, 0xc9, 0x03, 0x85, 0xcd, 0x20, 0x75, + 0xf9, 0xad, 0xc8, 0x03, 0x85, 0xcc, 0x20, 0x7a, + + 0xf9, 0x24, 0xbb, 0x50, 0x1e, 0xa2, 0x04, 0x20, + 0x91, 0xf9, 0xca, 0xd0, 0xfa, 0xa2, 0x0f, 0x20, + + 0x27, 0xf9, 0x20, 0x91, 0xf9, 0xa2, 0x13, 0xa0, + 0x04, 0xbd, 0xb2, 0x03, 0x20, 0x7a, 0xf9, 0xca, + + 0x88, 0xd0, 0xf6, 0x60, 0xad, 0x47, 0x02, 0xf0, + 0x03, 0x4c, 0x10, 0xe3, 0x20, 0x8e, 0xfb, 0x20, + + 0xe2, 0xfb, 0x20, 0xdc, 0xe7, 0xf0, 0xec, 0x20, + 0x46, 0xfa, 0x52, 0x45, 0x43, 0x4f, 0x52, 0x44, + + 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x52, 0x45, + 0x54, 0x55, 0x52, 0x4e, 0x00, 0x20, 0x95, 0xf9, + + 0x20, 0xe0, 0xff, 0xc9, 0x0d, 0xd0, 0xf6, 0x4c, + 0xe7, 0xff, 0xe6, 0xb1, 0xd0, 0x06, 0xe6, 0xb2, + + 0xd0, 0x02, 0xe6, 0xb3, 0x60, 0x48, 0x20, 0x91, + 0xf9, 0x68, 0x48, 0x4a, 0x4a, 0x4a, 0x4a, 0x20, + + 0x83, 0xf9, 0x68, 0x18, 0x29, 0x0f, 0x69, 0x30, + 0xc9, 0x3a, 0x90, 0x02, 0x69, 0x06, 0x4c, 0xee, + + 0xff, 0xa9, 0x20, 0xd0, 0xf9, 0x08, 0x24, 0xeb, + 0x30, 0x04, 0x24, 0xff, 0x30, 0x02, 0x28, 0x60, + + 0x20, 0x3b, 0xf3, 0x20, 0xf2, 0xfa, 0xa9, 0x7e, + 0x20, 0xf4, 0xff, 0x00, 0x11, 0x45, 0x73, 0x63, + + 0x61, 0x70, 0x65, 0x00, 0x98, 0xf0, 0x0d, 0x20, + 0x46, 0xfa, 0x0d, 0x4c, 0x6f, 0x61, 0x64, 0x69, + + 0x6e, 0x67, 0x0d, 0x00, 0x85, 0xba, 0xa2, 0xff, + 0xa5, 0xc1, 0xd0, 0x0d, 0x20, 0x72, 0xfa, 0x08, + + 0xa2, 0xff, 0xa0, 0x99, 0xa9, 0xfa, 0x28, 0xd0, + 0x1c, 0xa0, 0x8e, 0xa5, 0xc1, 0xf0, 0x04, 0xa9, + + 0xfa, 0xd0, 0x12, 0xad, 0xc6, 0x03, 0xc5, 0xb4, + 0xd0, 0x07, 0xad, 0xc7, 0x03, 0xc5, 0xb5, 0xf0, + + 0x13, 0xa0, 0xa4, 0xa9, 0xfa, 0x48, 0x98, 0x48, + 0x8a, 0x48, 0x20, 0xb6, 0xf8, 0x68, 0xaa, 0x68, + + 0xa8, 0x68, 0xd0, 0x14, 0x8a, 0x48, 0x20, 0xa9, + 0xf8, 0x20, 0xd6, 0xfa, 0x68, 0xaa, 0xa5, 0xbe, + + 0x05, 0xbf, 0xf0, 0x79, 0xa0, 0x8e, 0xa9, 0xfa, + 0xc6, 0xba, 0x48, 0x24, 0xeb, 0x30, 0x0d, 0x8a, + + 0x2d, 0x47, 0x02, 0xd0, 0x07, 0x8a, 0x29, 0x11, + 0x25, 0xbb, 0xf0, 0x10, 0x68, 0x85, 0xb9, 0x84, + + 0xb8, 0x20, 0x8b, 0xf6, 0x46, 0xeb, 0x20, 0xe8, + 0xfa, 0x6c, 0xb8, 0x00, 0x68, 0xc8, 0xd0, 0x03, + + 0x18, 0x69, 0x01, 0x48, 0x98, 0x48, 0x20, 0xdc, + 0xe7, 0xa8, 0x68, 0x85, 0xb8, 0x68, 0x85, 0xb9, + + 0x98, 0x08, 0xe6, 0xb8, 0xd0, 0x02, 0xe6, 0xb9, + 0xa0, 0x00, 0xb1, 0xb8, 0xf0, 0x0a, 0x28, 0x08, + + 0xf0, 0xf0, 0x20, 0xe3, 0xff, 0x4c, 0x52, 0xfa, + 0x28, 0xe6, 0xb8, 0xd0, 0x02, 0xe6, 0xb9, 0x6c, + + 0xb8, 0x00, 0xa2, 0xff, 0xe8, 0xbd, 0xd2, 0x03, + 0xd0, 0x07, 0x8a, 0xf0, 0x03, 0xbd, 0xb2, 0x03, + + 0x60, 0x20, 0xe3, 0xe4, 0x5d, 0xb2, 0x03, 0xb0, + 0x02, 0x29, 0xdf, 0xf0, 0xe7, 0x60, 0x00, 0xd8, + + 0x0d, 0x44, 0x61, 0x74, 0x61, 0x3f, 0x00, 0xd0, + 0x15, 0x00, 0xdb, 0x0d, 0x46, 0x69, 0x6c, 0x65, + + 0x3f, 0x00, 0xd0, 0x0a, 0x00, 0xda, 0x0d, 0x42, + 0x6c, 0x6f, 0x63, 0x6b, 0x3f, 0x00, 0xa5, 0xba, + + 0xf0, 0x21, 0x8a, 0xf0, 0x1e, 0xa9, 0x22, 0x24, + 0xbb, 0xf0, 0x18, 0x20, 0x46, 0xfb, 0xa8, 0x20, + + 0x4a, 0xfa, 0x0d, 0x07, 0x52, 0x65, 0x77, 0x69, + 0x6e, 0x64, 0x20, 0x74, 0x61, 0x70, 0x65, 0x0d, + + 0x0d, 0x00, 0x60, 0x20, 0x4d, 0xf2, 0xa5, 0xc2, + 0xf0, 0xf8, 0x20, 0x95, 0xf9, 0xad, 0x47, 0x02, + + 0xf0, 0xf4, 0x20, 0x88, 0xf5, 0x4c, 0xd6, 0xfa, + 0x20, 0xdc, 0xe7, 0xf0, 0x05, 0xa9, 0x07, 0x20, + + 0xee, 0xff, 0xa9, 0x80, 0x20, 0xbd, 0xfb, 0xa2, + 0x00, 0x20, 0x95, 0xfb, 0x08, 0x78, 0xad, 0x82, + + 0x02, 0x8d, 0x10, 0xfe, 0xa9, 0x00, 0x85, 0xea, + 0xf0, 0x01, 0x08, 0x20, 0x46, 0xfb, 0xad, 0x50, + + 0x02, 0x4c, 0x89, 0xe1, 0x28, 0x24, 0xff, 0x10, + 0x18, 0x60, 0xa5, 0xe3, 0x0a, 0x0a, 0x0a, 0x0a, + + 0x85, 0xbb, 0xad, 0xd1, 0x03, 0xd0, 0x08, 0xa5, + 0xe3, 0x29, 0xf0, 0x85, 0xbb, 0xa9, 0x06, 0x85, + + 0xc7, 0x58, 0x08, 0x78, 0x2c, 0x4f, 0x02, 0x10, + 0xdb, 0xa5, 0xea, 0x30, 0xd7, 0xa9, 0x01, 0x85, + + 0xea, 0x20, 0x46, 0xfb, 0x28, 0x60, 0xa9, 0x03, + 0xd0, 0x1b, 0xa9, 0x30, 0x85, 0xca, 0xd0, 0x13, + + 0xa9, 0x05, 0x8d, 0x10, 0xfe, 0xa2, 0xff, 0xca, + 0xd0, 0xfd, 0x86, 0xca, 0xa9, 0x85, 0x8d, 0x10, + + 0xfe, 0xa9, 0xd0, 0x05, 0xc6, 0x8d, 0x08, 0xfe, + 0x60, 0xae, 0xc6, 0x03, 0xac, 0xc7, 0x03, 0xe8, + + 0x86, 0xb4, 0xd0, 0x01, 0xc8, 0x84, 0xb5, 0x60, + 0xa0, 0x00, 0x84, 0xc0, 0x84, 0xbe, 0x84, 0xbf, + + 0x60, 0xa0, 0xff, 0xc8, 0xe8, 0xbd, 0x00, 0x03, + 0x99, 0xd2, 0x03, 0xd0, 0xf6, 0x60, 0xa0, 0x00, + + 0x58, 0xa2, 0x01, 0x84, 0xc3, 0xa9, 0x89, 0xa4, + 0xc3, 0x4c, 0xf4, 0xff, 0x85, 0xbc, 0x98, 0x4d, + + 0x47, 0x02, 0xa8, 0xa5, 0xe2, 0x25, 0xbc, 0x4a, + 0x88, 0xf0, 0x04, 0x4a, 0x88, 0xd0, 0x02, 0xb0, + + 0x4d, 0x00, 0xde, 0x43, 0x68, 0x61, 0x6e, 0x6e, + 0x65, 0x6c, 0x00, 0xa9, 0x01, 0x20, 0xd3, 0xfb, + + 0xf0, 0x3c, 0x8a, 0xa2, 0xb0, 0xa0, 0x00, 0x48, + 0xa9, 0xc0, 0x20, 0x06, 0x04, 0x90, 0xfb, 0x68, + + 0x4c, 0x06, 0x04, 0xaa, 0xa5, 0xb2, 0x25, 0xb3, + 0xc9, 0xff, 0xf0, 0x05, 0xad, 0x7a, 0x02, 0x29, + + 0x80, 0x60, 0xa9, 0x85, 0x8d, 0x10, 0xfe, 0x20, + 0x46, 0xfb, 0xa9, 0x10, 0x20, 0x63, 0xfb, 0x20, + + 0x95, 0xf9, 0xad, 0x08, 0xfe, 0x29, 0x02, 0xf0, + 0xf6, 0xa9, 0xaa, 0x8d, 0x09, 0xfe, 0x60, 0x00, + + 0x28, 0x43, 0x29, 0x20, 0x31, 0x39, 0x38, 0x31, + 0x20, 0x41, 0x63, 0x6f, 0x72, 0x6e, 0x20, 0x43, + + 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x72, 0x73, + 0x20, 0x4c, 0x74, 0x64, 0x2e, 0x54, 0x68, 0x61, + + 0x6e, 0x6b, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, + 0x64, 0x75, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x74, + + 0x68, 0x65, 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, + 0x77, 0x69, 0x6e, 0x67, 0x20, 0x63, 0x6f, 0x6e, + + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, + 0x73, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, + + 0x20, 0x64, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, + 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x66, 0x20, + + 0x74, 0x68, 0x65, 0x20, 0x42, 0x42, 0x43, 0x20, + 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x72, + + 0x20, 0x28, 0x61, 0x6d, 0x6f, 0x6e, 0x67, 0x20, + 0x6f, 0x74, 0x68, 0x65, 0x72, 0x73, 0x20, 0x74, + + 0x6f, 0x6f, 0x20, 0x6e, 0x75, 0x6d, 0x65, 0x72, + 0x6f, 0x75, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x6d, + + 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x3a, + 0x2d, 0x20, 0x44, 0x61, 0x76, 0x69, 0x64, 0x20, + + 0x41, 0x6c, 0x6c, 0x65, 0x6e, 0x2c, 0x42, 0x6f, + 0x62, 0x20, 0x41, 0x75, 0x73, 0x74, 0x69, 0x6e, + + 0x2c, 0x52, 0x61, 0x6d, 0x20, 0x42, 0x61, 0x6e, + 0x65, 0x72, 0x6a, 0x65, 0x65, 0x2c, 0x50, 0x61, + + 0x75, 0x6c, 0x20, 0x42, 0x6f, 0x6e, 0x64, 0x2c, + 0x41, 0x6c, 0x6c, 0x65, 0x6e, 0x20, 0x42, 0x6f, + + 0x6f, 0x74, 0x68, 0x72, 0x6f, 0x79, 0x64, 0x2c, + 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, + + 0x65, 0x2c, 0x43, 0x6c, 0x65, 0x61, 0x72, 0x74, + 0x6f, 0x6e, 0x65, 0x2c, 0x4a, 0x6f, 0x68, 0x6e, + + 0x20, 0x43, 0x6f, 0x6c, 0x6c, 0x2c, 0x4a, 0x6f, + 0x68, 0x6e, 0x20, 0x43, 0x6f, 0x78, 0x2c, 0x41, + + 0x6e, 0x64, 0x79, 0x20, 0x43, 0x72, 0x69, 0x70, + 0x70, 0x73, 0x2c, 0x43, 0x68, 0x72, 0x69, 0x73, + + 0x20, 0x43, 0x75, 0x72, 0x72, 0x79, 0x2c, 0x36, + 0x35, 0x30, 0x32, 0x20, 0x64, 0x65, 0x73, 0x69, + + 0x67, 0x6e, 0x65, 0x72, 0x73, 0x2c, 0x4a, 0x65, + 0x72, 0x65, 0x6d, 0x79, 0x20, 0x44, 0x69, 0x6f, + + 0x6e, 0x2c, 0x54, 0x69, 0x6d, 0x20, 0x44, 0x6f, + 0x62, 0x73, 0x6f, 0x6e, 0x2c, 0x4a, 0x6f, 0x65, + + 0x20, 0x44, 0x75, 0x6e, 0x6e, 0x2c, 0x50, 0x61, + 0x75, 0x6c, 0x20, 0x46, 0x61, 0x72, 0x72, 0x65, + + 0x6c, 0x6c, 0x2c, 0x46, 0x65, 0x72, 0x72, 0x61, + 0x6e, 0x74, 0x69, 0x2c, 0x53, 0x74, 0x65, 0x76, + + 0x65, 0x20, 0x46, 0x75, 0x72, 0x62, 0x65, 0x72, + 0x2c, 0x4a, 0x6f, 0x6e, 0x20, 0x47, 0x69, 0x62, + + 0x62, 0x6f, 0x6e, 0x73, 0x2c, 0x41, 0x6e, 0x64, + 0x72, 0x65, 0x77, 0x20, 0x47, 0x6f, 0x72, 0x64, + + 0x6f, 0x6e, 0x2c, 0x4c, 0x61, 0x77, 0x72, 0x65, + 0x6e, 0x63, 0x65, 0x20, 0x48, 0x61, 0x72, 0x64, + + 0x77, 0x69, 0x63, 0x6b, 0x2c, 0x44, 0x79, 0x6c, + 0x61, 0x6e, 0x20, 0x48, 0x61, 0x72, 0x72, 0x69, + + 0x73, 0x2c, 0x48, 0x65, 0x72, 0x6d, 0x61, 0x6e, + 0x6e, 0x20, 0x48, 0x61, 0x75, 0x73, 0x65, 0x72, + + 0x2c, 0x48, 0x69, 0x74, 0x61, 0x63, 0x68, 0x69, + 0x2c, 0x41, 0x6e, 0x64, 0x79, 0x20, 0x48, 0x6f, + + 0x70, 0x70, 0x65, 0x72, 0x2c, 0x49, 0x43, 0x4c, + 0x2c, 0x4d, 0x61, 0x72, 0x74, 0x69, 0x6e, 0x20, + + 0x4a, 0x61, 0x63, 0x6b, 0x73, 0x6f, 0x6e, 0x2c, + 0x42, 0x72, 0x69, 0x61, 0x6e, 0x20, 0x4a, 0x6f, + + 0x6e, 0x65, 0x73, 0x2c, 0x43, 0x68, 0x72, 0x69, + 0x73, 0x20, 0x4a, 0x6f, 0x72, 0x64, 0x61, 0x6e, + + 0x2c, 0x44, 0x61, 0x76, 0x69, 0x64, 0x20, 0x4b, + 0x69, 0x6e, 0x67, 0x2c, 0x44, 0x61, 0x76, 0x69, + + 0x64, 0x20, 0x4b, 0x69, 0x74, 0x73, 0x6f, 0x6e, + 0x2c, 0x50, 0x61, 0x75, 0x6c, 0x20, 0x4b, 0x72, + + 0x69, 0x77, 0x61, 0x63, 0x7a, 0x65, 0x6b, 0x2c, + 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x72, + + 0x20, 0x4c, 0x61, 0x62, 0x6f, 0x72, 0x61, 0x74, + 0x6f, 0x72, 0x79, 0x2c, 0x50, 0x65, 0x74, 0x65, + + 0x72, 0x20, 0x4d, 0x69, 0x6c, 0x6c, 0x65, 0x72, + 0x2c, 0x41, 0x72, 0x74, 0x68, 0x75, 0x72, 0x20, + + 0x4e, 0x6f, 0x72, 0x6d, 0x61, 0x6e, 0x2c, 0x47, + 0x6c, 0x79, 0x6e, 0x20, 0x50, 0x68, 0x69, 0x6c, + + 0x6c, 0x69, 0x70, 0x73, 0x2c, 0x4d, 0x69, 0x6b, + 0x65, 0x20, 0x50, 0x72, 0x65, 0x65, 0x73, 0x2c, + + 0x4a, 0x6f, 0x68, 0x6e, 0x20, 0x52, 0x61, 0x64, + 0x63, 0x6c, 0x69, 0x66, 0x66, 0x65, 0x2c, 0x57, + + 0x69, 0x6c, 0x62, 0x65, 0x72, 0x66, 0x6f, 0x72, + 0x63, 0x65, 0x20, 0x52, 0x6f, 0x61, 0x64, 0x2c, + + 0x50, 0x65, 0x74, 0x65, 0x72, 0x20, 0x52, 0x6f, + 0x62, 0x69, 0x6e, 0x73, 0x6f, 0x6e, 0x2c, 0x52, + + 0x69, 0x63, 0x68, 0x61, 0x72, 0x64, 0x20, 0x52, + 0x75, 0x73, 0x73, 0x65, 0x6c, 0x6c, 0x2c, 0x4b, + + 0x69, 0x6d, 0x20, 0x53, 0x70, 0x65, 0x6e, 0x63, + 0x65, 0x2d, 0x4a, 0x6f, 0x6e, 0x65, 0x73, 0x2c, + + 0x47, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20, 0x54, + 0x65, 0x62, 0x62, 0x79, 0x2c, 0x4a, 0x6f, 0x6e, + + 0x20, 0x54, 0x68, 0x61, 0x63, 0x6b, 0x72, 0x61, + 0x79, 0x2c, 0x43, 0x68, 0x72, 0x69, 0x73, 0x20, + + 0x54, 0x75, 0x72, 0x6e, 0x65, 0x72, 0x2c, 0x41, + 0x64, 0x72, 0x69, 0x61, 0x6e, 0x20, 0x57, 0x61, + + 0x72, 0x6e, 0x65, 0x72, 0x2c, 0x52, 0x6f, 0x67, + 0x65, 0x72, 0x20, 0x57, 0x69, 0x6c, 0x73, 0x6f, + + 0x6e, 0x2c, 0x41, 0x6c, 0x61, 0x6e, 0x20, 0x57, + 0x72, 0x69, 0x67, 0x68, 0x74, 0x2e, 0xcd, 0xd9, + + 0x20, 0x51, 0xff, 0x20, 0x51, 0xff, 0x20, 0x51, + 0xff, 0x20, 0x51, 0xff, 0x20, 0x51, 0xff, 0x20, + + 0x51, 0xff, 0x20, 0x51, 0xff, 0x20, 0x51, 0xff, + 0x20, 0x51, 0xff, 0x20, 0x51, 0xff, 0x20, 0x51, + + 0xff, 0x20, 0x51, 0xff, 0x20, 0x51, 0xff, 0x20, + 0x51, 0xff, 0x20, 0x51, 0xff, 0x20, 0x51, 0xff, + + 0x20, 0x51, 0xff, 0x20, 0x51, 0xff, 0x20, 0x51, + 0xff, 0x20, 0x51, 0xff, 0x20, 0x51, 0xff, 0x20, + + 0x51, 0xff, 0x20, 0x51, 0xff, 0x20, 0x51, 0xff, + 0x20, 0x51, 0xff, 0x20, 0x51, 0xff, 0x20, 0x51, + + 0xff, 0x48, 0x48, 0x48, 0x48, 0x48, 0x08, 0x48, + 0x8a, 0x48, 0x98, 0x48, 0xba, 0xa9, 0xff, 0x9d, + + 0x08, 0x01, 0xa9, 0x88, 0x9d, 0x07, 0x01, 0xbc, + 0x0a, 0x01, 0xb9, 0x9d, 0x0d, 0x9d, 0x05, 0x01, + + 0xb9, 0x9e, 0x0d, 0x9d, 0x06, 0x01, 0xa5, 0xf4, + 0x9d, 0x09, 0x01, 0xb9, 0x9f, 0x0d, 0x85, 0xf4, + + 0x8d, 0x30, 0xfe, 0x68, 0xa8, 0x68, 0xaa, 0x68, + 0x40, 0x08, 0x48, 0x8a, 0x48, 0xba, 0xbd, 0x02, + + 0x01, 0x9d, 0x05, 0x01, 0xbd, 0x03, 0x01, 0x9d, + 0x06, 0x01, 0x68, 0xaa, 0x68, 0x68, 0x68, 0x85, + + 0xf4, 0x8d, 0x30, 0xfe, 0x68, 0x28, 0x60, 0x8a, + 0xb0, 0x2a, 0xbc, 0x00, 0xfc, 0x60, 0xbc, 0x00, + + 0xfd, 0x60, 0xbc, 0x00, 0xfe, 0x60, 0x36, 0x40, + 0xd9, 0x4c, 0x0b, 0xdc, 0x4c, 0xc0, 0xc4, 0x4c, + + 0x94, 0xe4, 0x4c, 0x1e, 0xea, 0x4c, 0x2f, 0xea, + 0x4c, 0xc5, 0xde, 0x4c, 0xa4, 0xe0, 0x6c, 0x1c, + + 0x02, 0x6c, 0x1a, 0x02, 0x6c, 0x18, 0x02, 0x6c, + 0x16, 0x02, 0x6c, 0x14, 0x02, 0x6c, 0x12, 0x02, + + 0x6c, 0x10, 0x02, 0xc9, 0x0d, 0xd0, 0x07, 0xa9, + 0x0a, 0x20, 0xee, 0xff, 0xa9, 0x0d, 0x6c, 0x0e, + + 0x02, 0x6c, 0x0c, 0x02, 0x6c, 0x0a, 0x02, 0x6c, + 0x08, 0x02, 0x00, 0x0d, 0xcd, 0xd9, 0x1c, 0xdc + ] + +rom_basic2 = [ + 0xc9, 0x01, 0xf0, 0x1f, 0x60, 0xea, 0x60, 0x0e, + 0x01, 0x42, 0x41, 0x53, 0x49, 0x43, 0x00, 0x28, + + 0x43, 0x29, 0x31, 0x39, 0x38, 0x32, 0x20, 0x41, + 0x63, 0x6f, 0x72, 0x6e, 0x0a, 0x0d, 0x00, 0x00, + + 0x80, 0x00, 0x00, 0xa9, 0x84, 0x20, 0xf4, 0xff, + 0x86, 0x06, 0x84, 0x07, 0xa9, 0x83, 0x20, 0xf4, + + 0xff, 0x84, 0x18, 0xa2, 0x00, 0x86, 0x1f, 0x8e, + 0x02, 0x04, 0x8e, 0x03, 0x04, 0xca, 0x86, 0x23, + + 0xa2, 0x0a, 0x8e, 0x00, 0x04, 0xca, 0x8e, 0x01, + 0x04, 0xa9, 0x01, 0x25, 0x11, 0x05, 0x0d, 0x05, + + 0x0e, 0x05, 0x0f, 0x05, 0x10, 0xd0, 0x0c, 0xa9, + 0x41, 0x85, 0x0d, 0xa9, 0x52, 0x85, 0x0e, 0xa9, + + 0x57, 0x85, 0x0f, 0xa9, 0x02, 0x8d, 0x02, 0x02, + 0xa9, 0xb4, 0x8d, 0x03, 0x02, 0x58, 0x4c, 0xdd, + + 0x8a, 0x41, 0x4e, 0x44, 0x80, 0x00, 0x41, 0x42, + 0x53, 0x94, 0x00, 0x41, 0x43, 0x53, 0x95, 0x00, + + 0x41, 0x44, 0x56, 0x41, 0x4c, 0x96, 0x00, 0x41, + 0x53, 0x43, 0x97, 0x00, 0x41, 0x53, 0x4e, 0x98, + + 0x00, 0x41, 0x54, 0x4e, 0x99, 0x00, 0x41, 0x55, + 0x54, 0x4f, 0xc6, 0x10, 0x42, 0x47, 0x45, 0x54, + + 0x9a, 0x01, 0x42, 0x50, 0x55, 0x54, 0xd5, 0x03, + 0x43, 0x4f, 0x4c, 0x4f, 0x55, 0x52, 0xfb, 0x02, + + 0x43, 0x41, 0x4c, 0x4c, 0xd6, 0x02, 0x43, 0x48, + 0x41, 0x49, 0x4e, 0xd7, 0x02, 0x43, 0x48, 0x52, + + 0x24, 0xbd, 0x00, 0x43, 0x4c, 0x45, 0x41, 0x52, + 0xd8, 0x01, 0x43, 0x4c, 0x4f, 0x53, 0x45, 0xd9, + + 0x03, 0x43, 0x4c, 0x47, 0xda, 0x01, 0x43, 0x4c, + 0x53, 0xdb, 0x01, 0x43, 0x4f, 0x53, 0x9b, 0x00, + + 0x43, 0x4f, 0x55, 0x4e, 0x54, 0x9c, 0x01, 0x44, + 0x41, 0x54, 0x41, 0xdc, 0x20, 0x44, 0x45, 0x47, + + 0x9d, 0x00, 0x44, 0x45, 0x46, 0xdd, 0x00, 0x44, + 0x45, 0x4c, 0x45, 0x54, 0x45, 0xc7, 0x10, 0x44, + + 0x49, 0x56, 0x81, 0x00, 0x44, 0x49, 0x4d, 0xde, + 0x02, 0x44, 0x52, 0x41, 0x57, 0xdf, 0x02, 0x45, + + 0x4e, 0x44, 0x50, 0x52, 0x4f, 0x43, 0xe1, 0x01, + 0x45, 0x4e, 0x44, 0xe0, 0x01, 0x45, 0x4e, 0x56, + + 0x45, 0x4c, 0x4f, 0x50, 0x45, 0xe2, 0x02, 0x45, + 0x4c, 0x53, 0x45, 0x8b, 0x14, 0x45, 0x56, 0x41, + + 0x4c, 0xa0, 0x00, 0x45, 0x52, 0x4c, 0x9e, 0x01, + 0x45, 0x52, 0x52, 0x4f, 0x52, 0x85, 0x04, 0x45, + + 0x4f, 0x46, 0xc5, 0x01, 0x45, 0x4f, 0x52, 0x82, + 0x00, 0x45, 0x52, 0x52, 0x9f, 0x01, 0x45, 0x58, + + 0x50, 0xa1, 0x00, 0x45, 0x58, 0x54, 0xa2, 0x01, + 0x46, 0x4f, 0x52, 0xe3, 0x02, 0x46, 0x41, 0x4c, + + 0x53, 0x45, 0xa3, 0x01, 0x46, 0x4e, 0xa4, 0x08, + 0x47, 0x4f, 0x54, 0x4f, 0xe5, 0x12, 0x47, 0x45, + + 0x54, 0x24, 0xbe, 0x00, 0x47, 0x45, 0x54, 0xa5, + 0x00, 0x47, 0x4f, 0x53, 0x55, 0x42, 0xe4, 0x12, + + 0x47, 0x43, 0x4f, 0x4c, 0xe6, 0x02, 0x48, 0x49, + 0x4d, 0x45, 0x4d, 0x93, 0x43, 0x49, 0x4e, 0x50, + + 0x55, 0x54, 0xe8, 0x02, 0x49, 0x46, 0xe7, 0x02, + 0x49, 0x4e, 0x4b, 0x45, 0x59, 0x24, 0xbf, 0x00, + + 0x49, 0x4e, 0x4b, 0x45, 0x59, 0xa6, 0x00, 0x49, + 0x4e, 0x54, 0xa8, 0x00, 0x49, 0x4e, 0x53, 0x54, + + 0x52, 0x28, 0xa7, 0x00, 0x4c, 0x49, 0x53, 0x54, + 0xc9, 0x10, 0x4c, 0x49, 0x4e, 0x45, 0x86, 0x00, + + 0x4c, 0x4f, 0x41, 0x44, 0xc8, 0x02, 0x4c, 0x4f, + 0x4d, 0x45, 0x4d, 0x92, 0x43, 0x4c, 0x4f, 0x43, + + 0x41, 0x4c, 0xea, 0x02, 0x4c, 0x45, 0x46, 0x54, + 0x24, 0x28, 0xc0, 0x00, 0x4c, 0x45, 0x4e, 0xa9, + + 0x00, 0x4c, 0x45, 0x54, 0xe9, 0x04, 0x4c, 0x4f, + 0x47, 0xab, 0x00, 0x4c, 0x4e, 0xaa, 0x00, 0x4d, + + 0x49, 0x44, 0x24, 0x28, 0xc1, 0x00, 0x4d, 0x4f, + 0x44, 0x45, 0xeb, 0x02, 0x4d, 0x4f, 0x44, 0x83, + + 0x00, 0x4d, 0x4f, 0x56, 0x45, 0xec, 0x02, 0x4e, + 0x45, 0x58, 0x54, 0xed, 0x02, 0x4e, 0x45, 0x57, + + 0xca, 0x01, 0x4e, 0x4f, 0x54, 0xac, 0x00, 0x4f, + 0x4c, 0x44, 0xcb, 0x01, 0x4f, 0x4e, 0xee, 0x02, + + 0x4f, 0x46, 0x46, 0x87, 0x00, 0x4f, 0x52, 0x84, + 0x00, 0x4f, 0x50, 0x45, 0x4e, 0x49, 0x4e, 0x8e, + + 0x00, 0x4f, 0x50, 0x45, 0x4e, 0x4f, 0x55, 0x54, + 0xae, 0x00, 0x4f, 0x50, 0x45, 0x4e, 0x55, 0x50, + + 0xad, 0x00, 0x4f, 0x53, 0x43, 0x4c, 0x49, 0xff, + 0x02, 0x50, 0x52, 0x49, 0x4e, 0x54, 0xf1, 0x02, + + 0x50, 0x41, 0x47, 0x45, 0x90, 0x43, 0x50, 0x54, + 0x52, 0x8f, 0x43, 0x50, 0x49, 0xaf, 0x01, 0x50, + + 0x4c, 0x4f, 0x54, 0xf0, 0x02, 0x50, 0x4f, 0x49, + 0x4e, 0x54, 0x28, 0xb0, 0x00, 0x50, 0x52, 0x4f, + + 0x43, 0xf2, 0x0a, 0x50, 0x4f, 0x53, 0xb1, 0x01, + 0x52, 0x45, 0x54, 0x55, 0x52, 0x4e, 0xf8, 0x01, + + 0x52, 0x45, 0x50, 0x45, 0x41, 0x54, 0xf5, 0x00, + 0x52, 0x45, 0x50, 0x4f, 0x52, 0x54, 0xf6, 0x01, + + 0x52, 0x45, 0x41, 0x44, 0xf3, 0x02, 0x52, 0x45, + 0x4d, 0xf4, 0x20, 0x52, 0x55, 0x4e, 0xf9, 0x01, + + 0x52, 0x41, 0x44, 0xb2, 0x00, 0x52, 0x45, 0x53, + 0x54, 0x4f, 0x52, 0x45, 0xf7, 0x12, 0x52, 0x49, + + 0x47, 0x48, 0x54, 0x24, 0x28, 0xc2, 0x00, 0x52, + 0x4e, 0x44, 0xb3, 0x01, 0x52, 0x45, 0x4e, 0x55, + + 0x4d, 0x42, 0x45, 0x52, 0xcc, 0x10, 0x53, 0x54, + 0x45, 0x50, 0x88, 0x00, 0x53, 0x41, 0x56, 0x45, + + 0xcd, 0x02, 0x53, 0x47, 0x4e, 0xb4, 0x00, 0x53, + 0x49, 0x4e, 0xb5, 0x00, 0x53, 0x51, 0x52, 0xb6, + + 0x00, 0x53, 0x50, 0x43, 0x89, 0x00, 0x53, 0x54, + 0x52, 0x24, 0xc3, 0x00, 0x53, 0x54, 0x52, 0x49, + + 0x4e, 0x47, 0x24, 0x28, 0xc4, 0x00, 0x53, 0x4f, + 0x55, 0x4e, 0x44, 0xd4, 0x02, 0x53, 0x54, 0x4f, + + 0x50, 0xfa, 0x01, 0x54, 0x41, 0x4e, 0xb7, 0x00, + 0x54, 0x48, 0x45, 0x4e, 0x8c, 0x14, 0x54, 0x4f, + + 0xb8, 0x00, 0x54, 0x41, 0x42, 0x28, 0x8a, 0x00, + 0x54, 0x52, 0x41, 0x43, 0x45, 0xfc, 0x12, 0x54, + + 0x49, 0x4d, 0x45, 0x91, 0x43, 0x54, 0x52, 0x55, + 0x45, 0xb9, 0x01, 0x55, 0x4e, 0x54, 0x49, 0x4c, + + 0xfd, 0x02, 0x55, 0x53, 0x52, 0xba, 0x00, 0x56, + 0x44, 0x55, 0xef, 0x02, 0x56, 0x41, 0x4c, 0xbb, + + 0x00, 0x56, 0x50, 0x4f, 0x53, 0xbc, 0x01, 0x57, + 0x49, 0x44, 0x54, 0x48, 0xfe, 0x02, 0x50, 0x41, + + 0x47, 0x45, 0xd0, 0x00, 0x50, 0x54, 0x52, 0xcf, + 0x00, 0x54, 0x49, 0x4d, 0x45, 0xd1, 0x00, 0x4c, + + 0x4f, 0x4d, 0x45, 0x4d, 0xd2, 0x00, 0x48, 0x49, + 0x4d, 0x45, 0x4d, 0xd3, 0x00, 0x78, 0x47, 0xc0, + + 0xb4, 0xfc, 0x03, 0x6a, 0xd4, 0x33, 0x9e, 0xda, + 0x07, 0x6f, 0x8d, 0xf7, 0xc2, 0x9f, 0xa6, 0xe9, + + 0x91, 0x46, 0xca, 0x95, 0xb9, 0xad, 0xe2, 0x78, + 0xd1, 0xfe, 0xa8, 0xd1, 0x80, 0x7c, 0xcb, 0x41, + + 0x6d, 0xb1, 0x49, 0x88, 0x98, 0xb4, 0xbe, 0xdc, + 0xc4, 0xd2, 0x2f, 0x76, 0xbd, 0xbf, 0x26, 0xcc, + + 0x39, 0xee, 0x94, 0xc2, 0xb8, 0xac, 0x31, 0x24, + 0x9c, 0xda, 0xb6, 0xa3, 0xf3, 0x2a, 0x30, 0x83, + + 0xc9, 0x6f, 0x5d, 0x4c, 0x58, 0xd2, 0x2a, 0x8d, + 0x99, 0xbd, 0xc4, 0x7d, 0x7d, 0x2f, 0xe8, 0xc8, + + 0x56, 0x72, 0xc4, 0x88, 0xcc, 0x7a, 0xc2, 0x44, + 0xe4, 0x23, 0x9a, 0xe4, 0x95, 0x15, 0x2f, 0xf1, + + 0x9a, 0x04, 0x1f, 0x7d, 0xe4, 0xe4, 0xe6, 0xb6, + 0x11, 0xd0, 0x8e, 0x95, 0xb1, 0xa0, 0xc2, 0xbf, + + 0xbf, 0xae, 0xae, 0xae, 0xaf, 0xad, 0xa8, 0xab, + 0xac, 0xa8, 0xa9, 0xbf, 0xa9, 0xae, 0xab, 0xaf, + + 0xaf, 0xab, 0xaa, 0xbf, 0xae, 0xb1, 0xaf, 0xac, + 0xac, 0xac, 0xae, 0xa7, 0xab, 0xac, 0xbf, 0xbf, + + 0xab, 0xab, 0xab, 0xab, 0xaf, 0xab, 0xa9, 0xa7, + 0xa6, 0xae, 0xac, 0xab, 0xac, 0xab, 0xb3, 0xaf, + + 0xb0, 0xaf, 0xb0, 0xaf, 0xb0, 0xb0, 0xac, 0x90, + 0x8f, 0xbf, 0xb5, 0x8a, 0x8a, 0x8f, 0xbe, 0x98, + + 0xbf, 0x92, 0x92, 0x92, 0x92, 0xb4, 0xbf, 0x8e, + 0xbf, 0x92, 0xbf, 0x8e, 0x8e, 0x8b, 0x8b, 0x91, + + 0x93, 0x8a, 0x93, 0xb4, 0xb7, 0xb8, 0xb8, 0x93, + 0x98, 0xba, 0x8b, 0x93, 0x93, 0x93, 0xb6, 0xb9, + + 0x94, 0x93, 0x8d, 0x93, 0xbb, 0x8b, 0xbb, 0xbf, + 0xba, 0xb8, 0xbd, 0x8a, 0x93, 0x92, 0xbb, 0xb4, + + 0xbe, 0x4b, 0x83, 0x84, 0x89, 0x96, 0xb8, 0xb9, + 0xd8, 0xd9, 0xf0, 0x01, 0x10, 0x81, 0x90, 0x89, + + 0x93, 0xa3, 0xa4, 0xa9, 0x38, 0x39, 0x78, 0x01, + 0x13, 0x21, 0x63, 0x73, 0xb1, 0xa9, 0xc5, 0x0c, + + 0xc3, 0xd3, 0xc4, 0xf2, 0x41, 0x83, 0xb0, 0x81, + 0x43, 0x6c, 0x72, 0xec, 0xf2, 0xa3, 0xc3, 0x18, + + 0x19, 0x34, 0xb0, 0x72, 0x98, 0x99, 0x81, 0x98, + 0x99, 0x14, 0x35, 0x0a, 0x0d, 0x0d, 0x0d, 0x0d, + + 0x10, 0x10, 0x25, 0x25, 0x39, 0x41, 0x41, 0x41, + 0x41, 0x4a, 0x4a, 0x4c, 0x4c, 0x4c, 0x50, 0x50, + + 0x52, 0x53, 0x53, 0x53, 0x08, 0x08, 0x08, 0x09, + 0x09, 0x0a, 0x0a, 0x0a, 0x05, 0x15, 0x3e, 0x04, + + 0x0d, 0x30, 0x4c, 0x06, 0x32, 0x49, 0x49, 0x10, + 0x25, 0x0e, 0x0e, 0x09, 0x29, 0x2a, 0x30, 0x30, + + 0x4e, 0x4e, 0x4e, 0x3e, 0x16, 0x00, 0x18, 0xd8, + 0x58, 0xb8, 0xca, 0x88, 0xe8, 0xc8, 0xea, 0x48, + + 0x08, 0x68, 0x28, 0x40, 0x60, 0x38, 0xf8, 0x78, + 0xaa, 0xa8, 0xba, 0x8a, 0x9a, 0x98, 0x90, 0xb0, + + 0xf0, 0x30, 0xd0, 0x10, 0x50, 0x70, 0x21, 0x41, + 0x01, 0x61, 0xc1, 0xa1, 0xe1, 0x06, 0x46, 0x26, + + 0x66, 0xc6, 0xe6, 0xe0, 0xc0, 0x20, 0x4c, 0x20, + 0xa2, 0xa0, 0x81, 0x86, 0x84, 0xa9, 0xff, 0x85, + + 0x28, 0x4c, 0xa3, 0x8b, 0xa9, 0x03, 0x85, 0x28, + 0x20, 0x97, 0x8a, 0xc9, 0x5d, 0xf0, 0xee, 0x20, + + 0x6d, 0x98, 0xc6, 0x0a, 0x20, 0xba, 0x85, 0xc6, + 0x0a, 0xa5, 0x28, 0x4a, 0x90, 0x60, 0xa5, 0x1e, + + 0x69, 0x04, 0x85, 0x3f, 0xa5, 0x38, 0x20, 0x45, + 0xb5, 0xa5, 0x37, 0x20, 0x62, 0xb5, 0xa2, 0xfc, + + 0xa4, 0x39, 0x10, 0x02, 0xa4, 0x36, 0x84, 0x38, + 0xf0, 0x1c, 0xa0, 0x00, 0xe8, 0xd0, 0x0d, 0x20, + + 0x25, 0xbc, 0xa6, 0x3f, 0x20, 0x65, 0xb5, 0xca, + 0xd0, 0xfa, 0xa2, 0xfd, 0xb1, 0x3a, 0x20, 0x62, + + 0xb5, 0xc8, 0xc6, 0x38, 0xd0, 0xe6, 0xe8, 0x10, + 0x0c, 0x20, 0x65, 0xb5, 0x20, 0x58, 0xb5, 0x20, + + 0x58, 0xb5, 0x4c, 0x56, 0x85, 0xa0, 0x00, 0xb1, + 0x0b, 0xc9, 0x3a, 0xf0, 0x0a, 0xc9, 0x0d, 0xf0, + + 0x0a, 0x20, 0x0e, 0xb5, 0xc8, 0xd0, 0xf0, 0xc4, + 0x0a, 0x90, 0xf6, 0x20, 0x25, 0xbc, 0xa4, 0x0a, + + 0x88, 0xc8, 0xb1, 0x0b, 0xc9, 0x3a, 0xf0, 0x04, + 0xc9, 0x0d, 0xd0, 0xf5, 0x20, 0x59, 0x98, 0x88, + + 0xb1, 0x0b, 0xc9, 0x3a, 0xf0, 0x0c, 0xa5, 0x0c, + 0xc9, 0x07, 0xd0, 0x03, 0x4c, 0xf6, 0x8a, 0x20, + + 0x90, 0x98, 0x4c, 0x08, 0x85, 0x20, 0x82, 0x95, + 0xf0, 0x5a, 0xb0, 0x58, 0x20, 0x94, 0xbd, 0x20, + + 0x3a, 0xae, 0x85, 0x27, 0x20, 0xb4, 0xb4, 0x20, + 0x27, 0x88, 0xa2, 0x03, 0x20, 0x97, 0x8a, 0xa0, + + 0x00, 0x84, 0x3d, 0xc9, 0x3a, 0xf0, 0x64, 0xc9, + 0x0d, 0xf0, 0x60, 0xc9, 0x5c, 0xf0, 0x5c, 0xc9, + + 0x2e, 0xf0, 0xd2, 0xc6, 0x0a, 0xa4, 0x0a, 0xe6, + 0x0a, 0xb1, 0x0b, 0x30, 0x2a, 0xc9, 0x20, 0xf0, + + 0x10, 0xa0, 0x05, 0x0a, 0x0a, 0x0a, 0x0a, 0x26, + 0x3d, 0x26, 0x3e, 0x88, 0xd0, 0xf8, 0xca, 0xd0, + + 0xe4, 0xa2, 0x3a, 0xa5, 0x3d, 0xdd, 0x50, 0x84, + 0xd0, 0x07, 0xbc, 0x8a, 0x84, 0xc4, 0x3e, 0xf0, + + 0x1f, 0xca, 0xd0, 0xf1, 0x4c, 0x2a, 0x98, 0xa2, + 0x22, 0xc9, 0x80, 0xf0, 0x13, 0xe8, 0xc9, 0x82, + + 0xf0, 0x0e, 0xe8, 0xc9, 0x84, 0xd0, 0xed, 0xe6, + 0x0a, 0xc8, 0xb1, 0x0b, 0xc9, 0x41, 0xd0, 0xe4, + + 0xbd, 0xc4, 0x84, 0x85, 0x29, 0xa0, 0x01, 0xe0, + 0x1a, 0xb0, 0x48, 0xad, 0x40, 0x04, 0x85, 0x37, + + 0x84, 0x39, 0xa6, 0x28, 0xe0, 0x04, 0xae, 0x41, + 0x04, 0x86, 0x38, 0x90, 0x06, 0xad, 0x3c, 0x04, + + 0xae, 0x3d, 0x04, 0x85, 0x3a, 0x86, 0x3b, 0x98, + 0xf0, 0x28, 0x10, 0x04, 0xa4, 0x36, 0xf0, 0x22, + + 0x88, 0xb9, 0x29, 0x00, 0x24, 0x39, 0x10, 0x03, + 0xb9, 0x00, 0x06, 0x91, 0x3a, 0xee, 0x40, 0x04, + + 0xd0, 0x03, 0xee, 0x41, 0x04, 0x90, 0x08, 0xee, + 0x3c, 0x04, 0xd0, 0x03, 0xee, 0x3d, 0x04, 0x98, + + 0xd0, 0xde, 0x60, 0xe0, 0x22, 0xb0, 0x40, 0x20, + 0x21, 0x88, 0x18, 0xa5, 0x2a, 0xed, 0x40, 0x04, + + 0xa8, 0xa5, 0x2b, 0xed, 0x41, 0x04, 0xc0, 0x01, + 0x88, 0xe9, 0x00, 0xf0, 0x25, 0xc9, 0xff, 0xf0, + + 0x1c, 0xa5, 0x28, 0x4a, 0xf0, 0x0f, 0x00, 0x01, + 0x4f, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x72, + + 0x61, 0x6e, 0x67, 0x65, 0x00, 0xa8, 0x84, 0x2a, + 0xa0, 0x02, 0x4c, 0x2b, 0x86, 0x98, 0x30, 0xf6, + + 0x10, 0xdf, 0x98, 0x10, 0xf1, 0x30, 0xda, 0xe0, + 0x29, 0xb0, 0x18, 0x20, 0x97, 0x8a, 0xc9, 0x23, + + 0xd0, 0x18, 0x20, 0x2f, 0x88, 0x20, 0x21, 0x88, + 0xa5, 0x2b, 0xf0, 0xdc, 0x00, 0x02, 0x42, 0x79, + + 0x74, 0x65, 0x00, 0xe0, 0x36, 0xd0, 0x68, 0x20, + 0x97, 0x8a, 0xc9, 0x28, 0xd0, 0x37, 0x20, 0x21, + + 0x88, 0x20, 0x97, 0x8a, 0xc9, 0x29, 0xd0, 0x13, + 0x20, 0x97, 0x8a, 0xc9, 0x2c, 0xd0, 0x1e, 0x20, + + 0x2c, 0x88, 0x20, 0x97, 0x8a, 0xc9, 0x59, 0xd0, + 0x14, 0xf0, 0xcd, 0xc9, 0x2c, 0xd0, 0x0e, 0x20, + + 0x97, 0x8a, 0xc9, 0x58, 0xd0, 0x07, 0x20, 0x97, + 0x8a, 0xc9, 0x29, 0xf0, 0xbb, 0x00, 0x03, 0x49, + + 0x6e, 0x64, 0x65, 0x78, 0x00, 0xc6, 0x0a, 0x20, + 0x21, 0x88, 0x20, 0x97, 0x8a, 0xc9, 0x2c, 0xd0, + + 0x14, 0x20, 0x2c, 0x88, 0x20, 0x97, 0x8a, 0xc9, + 0x58, 0xf0, 0x0a, 0xc9, 0x59, 0xd0, 0xde, 0x20, + + 0x2f, 0x88, 0x4c, 0x9a, 0x87, 0x20, 0x32, 0x88, + 0xa5, 0x2b, 0xd0, 0xf3, 0x4c, 0xa8, 0x86, 0xe0, + + 0x2f, 0xb0, 0x2b, 0xe0, 0x2d, 0xb0, 0x09, 0x20, + 0x97, 0x8a, 0xc9, 0x41, 0xf0, 0x19, 0xc6, 0x0a, + + 0x20, 0x21, 0x88, 0x20, 0x97, 0x8a, 0xc9, 0x2c, + 0xd0, 0xde, 0x20, 0x2c, 0x88, 0x20, 0x97, 0x8a, + + 0xc9, 0x58, 0xf0, 0xd4, 0x4c, 0x0d, 0x87, 0x20, + 0x32, 0x88, 0xa0, 0x01, 0xd0, 0x2e, 0xe0, 0x32, + + 0xb0, 0x16, 0xe0, 0x31, 0xf0, 0x0c, 0x20, 0x97, + 0x8a, 0xc9, 0x23, 0xd0, 0x03, 0x4c, 0xc5, 0x86, + + 0xc6, 0x0a, 0x20, 0x21, 0x88, 0x4c, 0x35, 0x87, + 0xe0, 0x33, 0xf0, 0x0b, 0xb0, 0x24, 0x20, 0x97, + + 0x8a, 0xc9, 0x28, 0xf0, 0x0a, 0xc6, 0x0a, 0x20, + 0x21, 0x88, 0xa0, 0x03, 0x4c, 0x2b, 0x86, 0x20, + + 0x2c, 0x88, 0x20, 0x2c, 0x88, 0x20, 0x21, 0x88, + 0x20, 0x97, 0x8a, 0xc9, 0x29, 0xf0, 0xeb, 0x4c, + + 0x0d, 0x87, 0xe0, 0x39, 0xb0, 0x5d, 0xa5, 0x3d, + 0x49, 0x01, 0x29, 0x1f, 0x48, 0xe0, 0x37, 0xb0, + + 0x2f, 0x20, 0x97, 0x8a, 0xc9, 0x23, 0xd0, 0x04, + 0x68, 0x4c, 0xc5, 0x86, 0xc6, 0x0a, 0x20, 0x21, + + 0x88, 0x68, 0x85, 0x37, 0x20, 0x97, 0x8a, 0xc9, + 0x2c, 0xf0, 0x03, 0x4c, 0x35, 0x87, 0x20, 0x97, + + 0x8a, 0x29, 0x1f, 0xc5, 0x37, 0xd0, 0x06, 0x20, + 0x2c, 0x88, 0x4c, 0x35, 0x87, 0x4c, 0x0d, 0x87, + + 0x20, 0x21, 0x88, 0x68, 0x85, 0x37, 0x20, 0x97, + 0x8a, 0xc9, 0x2c, 0xd0, 0x13, 0x20, 0x97, 0x8a, + + 0x29, 0x1f, 0xc5, 0x37, 0xd0, 0xe7, 0x20, 0x2c, + 0x88, 0xa5, 0x2b, 0xf0, 0x03, 0x4c, 0xcc, 0x86, + + 0x4c, 0x38, 0x87, 0xd0, 0x25, 0x20, 0x21, 0x88, + 0xa5, 0x2a, 0x85, 0x28, 0xa0, 0x00, 0x4c, 0x2b, + + 0x86, 0x20, 0x1d, 0x9b, 0x20, 0xf0, 0x92, 0xa4, + 0x1b, 0x84, 0x0a, 0x60, 0x20, 0x2f, 0x88, 0x20, + + 0x32, 0x88, 0xa5, 0x29, 0x18, 0x69, 0x04, 0x85, + 0x29, 0x60, 0xa2, 0x01, 0xa4, 0x0a, 0xe6, 0x0a, + + 0xb1, 0x0b, 0xc9, 0x42, 0xf0, 0x12, 0xe8, 0xc9, + 0x57, 0xf0, 0x0d, 0xa2, 0x04, 0xc9, 0x44, 0xf0, + + 0x07, 0xc9, 0x53, 0xf0, 0x15, 0x4c, 0x2a, 0x98, + 0x8a, 0x48, 0x20, 0x21, 0x88, 0xa2, 0x29, 0x20, + + 0x44, 0xbe, 0x68, 0xa8, 0x4c, 0x2b, 0x86, 0x4c, + 0x0e, 0x8c, 0xa5, 0x28, 0x48, 0x20, 0x1d, 0x9b, + + 0xd0, 0xf5, 0x68, 0x85, 0x28, 0x20, 0x27, 0x88, + 0xa0, 0xff, 0xd0, 0xe8, 0x48, 0x18, 0x98, 0x65, + + 0x37, 0x85, 0x39, 0xa0, 0x00, 0x98, 0x65, 0x38, + 0x85, 0x3a, 0x68, 0x91, 0x37, 0xc8, 0xb1, 0x39, + + 0x91, 0x37, 0xc9, 0x0d, 0xd0, 0xf7, 0x60, 0x29, + 0x0f, 0x85, 0x3d, 0x84, 0x3e, 0xc8, 0xb1, 0x37, + + 0xc9, 0x3a, 0xb0, 0x36, 0xc9, 0x30, 0x90, 0x32, + 0x29, 0x0f, 0x48, 0xa6, 0x3e, 0xa5, 0x3d, 0x0a, + + 0x26, 0x3e, 0x30, 0x21, 0x0a, 0x26, 0x3e, 0x30, + 0x1c, 0x65, 0x3d, 0x85, 0x3d, 0x8a, 0x65, 0x3e, + + 0x06, 0x3d, 0x2a, 0x30, 0x10, 0xb0, 0x0e, 0x85, + 0x3e, 0x68, 0x65, 0x3d, 0x85, 0x3d, 0x90, 0xcd, + + 0xe6, 0x3e, 0x10, 0xc9, 0x48, 0x68, 0xa0, 0x00, + 0x38, 0x60, 0x88, 0xa9, 0x8d, 0x20, 0x7c, 0x88, + + 0xa5, 0x37, 0x69, 0x02, 0x85, 0x39, 0xa5, 0x38, + 0x69, 0x00, 0x85, 0x3a, 0xb1, 0x37, 0x91, 0x39, + + 0x88, 0xd0, 0xf9, 0xa0, 0x03, 0xa5, 0x3e, 0x09, + 0x40, 0x91, 0x37, 0x88, 0xa5, 0x3d, 0x29, 0x3f, + + 0x09, 0x40, 0x91, 0x37, 0x88, 0xa5, 0x3d, 0x29, + 0xc0, 0x85, 0x3d, 0xa5, 0x3e, 0x29, 0xc0, 0x4a, + + 0x4a, 0x05, 0x3d, 0x4a, 0x4a, 0x49, 0x54, 0x91, + 0x37, 0x20, 0x44, 0x89, 0x20, 0x44, 0x89, 0x20, + + 0x44, 0x89, 0xa0, 0x00, 0x18, 0x60, 0xc9, 0x7b, + 0xb0, 0xfa, 0xc9, 0x5f, 0xb0, 0x0e, 0xc9, 0x5b, + + 0xb0, 0xf2, 0xc9, 0x41, 0xb0, 0x06, 0xc9, 0x3a, + 0xb0, 0xea, 0xc9, 0x30, 0x60, 0xc9, 0x2e, 0xd0, + + 0xf5, 0x60, 0xb1, 0x37, 0xe6, 0x37, 0xd0, 0x02, + 0xe6, 0x38, 0x60, 0x20, 0x44, 0x89, 0xb1, 0x37, + + 0x60, 0xa0, 0x00, 0x84, 0x3b, 0x84, 0x3c, 0xb1, + 0x37, 0xc9, 0x0d, 0xf0, 0xed, 0xc9, 0x20, 0xd0, + + 0x05, 0x20, 0x44, 0x89, 0xd0, 0xf1, 0xc9, 0x26, + 0xd0, 0x12, 0x20, 0x4b, 0x89, 0x20, 0x36, 0x89, + + 0xb0, 0xf8, 0xc9, 0x41, 0x90, 0xe1, 0xc9, 0x47, + 0x90, 0xf0, 0xb0, 0xdb, 0xc9, 0x22, 0xd0, 0x0c, + + 0x20, 0x4b, 0x89, 0xc9, 0x22, 0xf0, 0xda, 0xc9, + 0x0d, 0xd0, 0xf5, 0x60, 0xc9, 0x3a, 0xd0, 0x06, + + 0x84, 0x3b, 0x84, 0x3c, 0xf0, 0xcb, 0xc9, 0x2c, + 0xf0, 0xc7, 0xc9, 0x2a, 0xd0, 0x05, 0xa5, 0x3b, + + 0xd0, 0x41, 0x60, 0xc9, 0x2e, 0xf0, 0x0e, 0x20, + 0x36, 0x89, 0x90, 0x33, 0xa6, 0x3c, 0xf0, 0x05, + + 0x20, 0x97, 0x88, 0x90, 0x34, 0xb1, 0x37, 0x20, + 0x3d, 0x89, 0x90, 0x06, 0x20, 0x44, 0x89, 0x4c, + + 0xb5, 0x89, 0xa2, 0xff, 0x86, 0x3b, 0x84, 0x3c, + 0x4c, 0x57, 0x89, 0x20, 0x26, 0x89, 0x90, 0x13, + + 0xa0, 0x00, 0xb1, 0x37, 0x20, 0x26, 0x89, 0x90, + 0xe9, 0x20, 0x44, 0x89, 0x4c, 0xd2, 0x89, 0xc9, + + 0x41, 0xb0, 0x09, 0xa2, 0xff, 0x86, 0x3b, 0x84, + 0x3c, 0x4c, 0x61, 0x89, 0xc9, 0x58, 0xb0, 0xdb, + + 0xa2, 0x71, 0x86, 0x39, 0xa2, 0x80, 0x86, 0x3a, + 0xd1, 0x39, 0x90, 0xd6, 0xd0, 0x0f, 0xc8, 0xb1, + + 0x39, 0x30, 0x34, 0xd1, 0x37, 0xf0, 0xf7, 0xb1, + 0x37, 0xc9, 0x2e, 0xf0, 0x0b, 0xc8, 0xb1, 0x39, + + 0x10, 0xfb, 0xc9, 0xfe, 0xd0, 0x0f, 0xb0, 0xb8, + 0xc8, 0xb1, 0x39, 0x30, 0x1a, 0xe6, 0x39, 0xd0, + + 0xf8, 0xe6, 0x3a, 0xd0, 0xf4, 0x38, 0xc8, 0x98, + 0x65, 0x39, 0x85, 0x39, 0x90, 0x02, 0xe6, 0x3a, + + 0xa0, 0x00, 0xb1, 0x37, 0x4c, 0xf8, 0x89, 0xaa, + 0xc8, 0xb1, 0x39, 0x85, 0x3d, 0x88, 0x4a, 0x90, + + 0x07, 0xb1, 0x37, 0x20, 0x26, 0x89, 0xb0, 0x88, + 0x8a, 0x24, 0x3d, 0x50, 0x07, 0xa6, 0x3b, 0xd0, + + 0x03, 0x18, 0x69, 0x40, 0x88, 0x20, 0x7c, 0x88, + 0xa0, 0x00, 0xa2, 0xff, 0xa5, 0x3d, 0x4a, 0x4a, + + 0x90, 0x04, 0x86, 0x3b, 0x84, 0x3c, 0x4a, 0x90, + 0x04, 0x84, 0x3b, 0x84, 0x3c, 0x4a, 0x90, 0x11, + + 0x48, 0xc8, 0xb1, 0x37, 0x20, 0x26, 0x89, 0x90, + 0x06, 0x20, 0x44, 0x89, 0x4c, 0x72, 0x8a, 0x88, + + 0x68, 0x4a, 0x90, 0x02, 0x86, 0x3c, 0x4a, 0xb0, + 0x0d, 0x4c, 0x61, 0x89, 0xa4, 0x1b, 0xe6, 0x1b, + + 0xb1, 0x19, 0xc9, 0x20, 0xf0, 0xf6, 0x60, 0xa4, + 0x0a, 0xe6, 0x0a, 0xb1, 0x0b, 0xc9, 0x20, 0xf0, + + 0xf6, 0x60, 0x00, 0x05, 0x4d, 0x69, 0x73, 0x73, + 0x69, 0x6e, 0x67, 0x20, 0x2c, 0x00, 0x20, 0x8c, + + 0x8a, 0xc9, 0x2c, 0xd0, 0xed, 0x60, 0x20, 0x57, + 0x98, 0xa5, 0x18, 0x85, 0x38, 0xa9, 0x00, 0x85, + + 0x37, 0x91, 0x37, 0x20, 0x6f, 0xbe, 0xd0, 0x2b, + 0x20, 0x57, 0x98, 0x20, 0x6f, 0xbe, 0xd0, 0x26, + + 0x20, 0x57, 0x98, 0x00, 0x00, 0x53, 0x54, 0x4f, + 0x50, 0x00, 0x20, 0x57, 0x98, 0xa9, 0x0d, 0xa4, + + 0x18, 0x84, 0x13, 0xa0, 0x00, 0x84, 0x12, 0x84, + 0x20, 0x91, 0x12, 0xa9, 0xff, 0xc8, 0x91, 0x12, + + 0xc8, 0x84, 0x12, 0x20, 0x20, 0xbd, 0xa0, 0x07, + 0x84, 0x0c, 0xa0, 0x00, 0x84, 0x0b, 0xa9, 0x33, + + 0x85, 0x16, 0xa9, 0xb4, 0x85, 0x17, 0xa9, 0x3e, + 0x20, 0x02, 0xbc, 0xa9, 0x33, 0x85, 0x16, 0xa9, + + 0xb4, 0x85, 0x17, 0xa2, 0xff, 0x86, 0x28, 0x86, + 0x3c, 0x9a, 0x20, 0x3a, 0xbd, 0xa8, 0xa5, 0x0b, + + 0x85, 0x37, 0xa5, 0x0c, 0x85, 0x38, 0x84, 0x3b, + 0x84, 0x0a, 0x20, 0x57, 0x89, 0x20, 0xdf, 0x97, + + 0x90, 0x06, 0x20, 0x8d, 0xbc, 0x4c, 0xf3, 0x8a, + 0x20, 0x97, 0x8a, 0xc9, 0xc6, 0xb0, 0x72, 0x90, + + 0x7e, 0x4c, 0xf6, 0x8a, 0x4c, 0x04, 0x85, 0xba, + 0xe0, 0xfc, 0xb0, 0x0d, 0xad, 0xff, 0x01, 0xc9, + + 0xa4, 0xd0, 0x06, 0x20, 0x1d, 0x9b, 0x4c, 0x4c, + 0x98, 0x00, 0x07, 0x4e, 0x6f, 0x20, 0xa4, 0x00, + + 0xa4, 0x0a, 0x88, 0xb1, 0x0b, 0xc9, 0x3d, 0xf0, + 0xde, 0xc9, 0x2a, 0xf0, 0x06, 0xc9, 0x5b, 0xf0, + + 0xd3, 0xd0, 0x23, 0x20, 0x6d, 0x98, 0xa6, 0x0b, + 0xa4, 0x0c, 0x20, 0xf7, 0xff, 0xa9, 0x0d, 0xa4, + + 0x0a, 0x88, 0xc8, 0xd1, 0x0b, 0xd0, 0xfb, 0xc9, + 0x8b, 0xf0, 0xf2, 0xa5, 0x0c, 0xc9, 0x07, 0xf0, + + 0xb0, 0x20, 0x90, 0x98, 0xd0, 0x0d, 0xc6, 0x0a, + 0x20, 0x57, 0x98, 0xa0, 0x00, 0xb1, 0x0b, 0xc9, + + 0x3a, 0xd0, 0xe4, 0xa4, 0x0a, 0xe6, 0x0a, 0xb1, + 0x0b, 0xc9, 0x20, 0xf0, 0xf6, 0xc9, 0xcf, 0x90, + + 0x0e, 0xaa, 0xbd, 0xdf, 0x82, 0x85, 0x37, 0xbd, + 0x51, 0x83, 0x85, 0x38, 0x6c, 0x37, 0x00, 0xa6, + + 0x0b, 0x86, 0x19, 0xa6, 0x0c, 0x86, 0x1a, 0x84, + 0x1b, 0x20, 0xdd, 0x95, 0xd0, 0x1b, 0xb0, 0x90, + + 0x86, 0x1b, 0x20, 0x41, 0x98, 0x20, 0xfc, 0x94, + 0xa2, 0x05, 0xe4, 0x2c, 0xd0, 0x01, 0xe8, 0x20, + + 0x31, 0x95, 0xc6, 0x0a, 0x20, 0x82, 0x95, 0xf0, + 0x22, 0x90, 0x10, 0x20, 0x94, 0xbd, 0x20, 0x13, + + 0x98, 0xa5, 0x27, 0xd0, 0x19, 0x20, 0x1e, 0x8c, + 0x4c, 0x9b, 0x8b, 0x20, 0x94, 0xbd, 0x20, 0x13, + + 0x98, 0xa5, 0x27, 0xf0, 0x09, 0x20, 0xb4, 0xb4, + 0x4c, 0x9b, 0x8b, 0x4c, 0x2a, 0x98, 0x00, 0x06, + + 0x54, 0x79, 0x70, 0x65, 0x20, 0x6d, 0x69, 0x73, + 0x6d, 0x61, 0x74, 0x63, 0x68, 0x00, 0x20, 0xea, + + 0xbd, 0xa5, 0x2c, 0xc9, 0x80, 0xf0, 0x7b, 0xa0, + 0x02, 0xb1, 0x2a, 0xc5, 0x36, 0xb0, 0x55, 0xa5, + + 0x02, 0x85, 0x2c, 0xa5, 0x03, 0x85, 0x2d, 0xa5, + 0x36, 0xc9, 0x08, 0x90, 0x06, 0x69, 0x07, 0x90, + + 0x02, 0xa9, 0xff, 0x18, 0x48, 0xaa, 0xb1, 0x2a, + 0xa0, 0x00, 0x71, 0x2a, 0x45, 0x02, 0xd0, 0x0f, + + 0xc8, 0x71, 0x2a, 0x45, 0x03, 0xd0, 0x08, 0x85, + 0x2d, 0x8a, 0xc8, 0x38, 0xf1, 0x2a, 0xaa, 0x8a, + + 0x18, 0x65, 0x02, 0xa8, 0xa5, 0x03, 0x69, 0x00, + 0xc4, 0x04, 0xaa, 0xe5, 0x05, 0xb0, 0x48, 0x84, + + 0x02, 0x86, 0x03, 0x68, 0xa0, 0x02, 0x91, 0x2a, + 0x88, 0xa5, 0x2d, 0xf0, 0x07, 0x91, 0x2a, 0x88, + + 0xa5, 0x2c, 0x91, 0x2a, 0xa0, 0x03, 0xa5, 0x36, + 0x91, 0x2a, 0xf0, 0x15, 0x88, 0x88, 0xb1, 0x2a, + + 0x85, 0x2d, 0x88, 0xb1, 0x2a, 0x85, 0x2c, 0xb9, + 0x00, 0x06, 0x91, 0x2c, 0xc8, 0xc4, 0x36, 0xd0, + + 0xf6, 0x60, 0x20, 0xba, 0xbe, 0xc0, 0x00, 0xf0, + 0x0b, 0xb9, 0x00, 0x06, 0x91, 0x2a, 0x88, 0xd0, + + 0xf8, 0xad, 0x00, 0x06, 0x91, 0x2a, 0x60, 0x00, + 0x00, 0x4e, 0x6f, 0x20, 0x72, 0x6f, 0x6f, 0x6d, + + 0x00, 0xa5, 0x39, 0xc9, 0x80, 0xf0, 0x27, 0x90, + 0x3a, 0xa0, 0x00, 0xb1, 0x04, 0xaa, 0xf0, 0x15, + + 0xb1, 0x37, 0xe9, 0x01, 0x85, 0x39, 0xc8, 0xb1, + 0x37, 0xe9, 0x00, 0x85, 0x3a, 0xb1, 0x04, 0x91, + + 0x39, 0xc8, 0xca, 0xd0, 0xf8, 0xa1, 0x04, 0xa0, + 0x03, 0x91, 0x37, 0x4c, 0xdc, 0xbd, 0xa0, 0x00, + + 0xb1, 0x04, 0xaa, 0xf0, 0x0a, 0xc8, 0xb1, 0x04, + 0x88, 0x91, 0x37, 0xc8, 0xca, 0xd0, 0xf6, 0xa9, + + 0x0d, 0xd0, 0xe6, 0xa0, 0x00, 0xb1, 0x04, 0x91, + 0x37, 0xc8, 0xc4, 0x39, 0xb0, 0x18, 0xb1, 0x04, + + 0x91, 0x37, 0xc8, 0xb1, 0x04, 0x91, 0x37, 0xc8, + 0xb1, 0x04, 0x91, 0x37, 0xc8, 0xc4, 0x39, 0xb0, + + 0x05, 0xb1, 0x04, 0x91, 0x37, 0xc8, 0x98, 0x18, + 0x4c, 0xe1, 0xbd, 0xc6, 0x0a, 0x20, 0xa9, 0xbf, + + 0x98, 0x48, 0x20, 0x8c, 0x8a, 0xc9, 0x2c, 0xd0, + 0x3e, 0x20, 0x29, 0x9b, 0x20, 0x85, 0xa3, 0x68, + + 0xa8, 0xa5, 0x27, 0x20, 0xd4, 0xff, 0xaa, 0xf0, + 0x1b, 0x30, 0x0c, 0xa2, 0x03, 0xb5, 0x2a, 0x20, + + 0xd4, 0xff, 0xca, 0x10, 0xf8, 0x30, 0xd9, 0xa2, + 0x04, 0xbd, 0x6c, 0x04, 0x20, 0xd4, 0xff, 0xca, + + 0x10, 0xf7, 0x30, 0xcc, 0xa5, 0x36, 0x20, 0xd4, + 0xff, 0xaa, 0xf0, 0xc4, 0xbd, 0xff, 0x05, 0x20, + + 0xd4, 0xff, 0xca, 0xd0, 0xf7, 0xf0, 0xb9, 0x68, + 0x84, 0x0a, 0x4c, 0x98, 0x8b, 0x20, 0x25, 0xbc, + + 0x4c, 0x96, 0x8b, 0xa9, 0x00, 0x85, 0x14, 0x85, + 0x15, 0x20, 0x97, 0x8a, 0xc9, 0x3a, 0xf0, 0xf0, + + 0xc9, 0x0d, 0xf0, 0xec, 0xc9, 0x8b, 0xf0, 0xe8, + 0xd0, 0x38, 0x20, 0x97, 0x8a, 0xc9, 0x23, 0xf0, + + 0x8a, 0xc6, 0x0a, 0x4c, 0xbb, 0x8d, 0xad, 0x00, + 0x04, 0xf0, 0x10, 0xa5, 0x1e, 0xf0, 0x0c, 0xed, + + 0x00, 0x04, 0xb0, 0xf9, 0xa8, 0x20, 0x65, 0xb5, + 0xc8, 0xd0, 0xfa, 0x18, 0xad, 0x00, 0x04, 0x85, + + 0x14, 0x66, 0x15, 0x20, 0x97, 0x8a, 0xc9, 0x3a, + 0xf0, 0xb3, 0xc9, 0x0d, 0xf0, 0xaf, 0xc9, 0x8b, + + 0xf0, 0xab, 0xc9, 0x7e, 0xf0, 0xeb, 0xc9, 0x2c, + 0xf0, 0xcc, 0xc9, 0x3b, 0xf0, 0xa5, 0x20, 0x70, + + 0x8e, 0x90, 0xe0, 0xa5, 0x14, 0x48, 0xa5, 0x15, + 0x48, 0xc6, 0x1b, 0x20, 0x29, 0x9b, 0x68, 0x85, + + 0x15, 0x68, 0x85, 0x14, 0xa5, 0x1b, 0x85, 0x0a, + 0x98, 0xf0, 0x13, 0x20, 0xdf, 0x9e, 0xa5, 0x14, + + 0x38, 0xe5, 0x36, 0x90, 0x09, 0xf0, 0x07, 0xa8, + 0x20, 0x65, 0xb5, 0x88, 0xd0, 0xfa, 0xa5, 0x36, + + 0xf0, 0xb1, 0xa0, 0x00, 0xb9, 0x00, 0x06, 0x20, + 0x58, 0xb5, 0xc8, 0xc4, 0x36, 0xd0, 0xf5, 0xf0, + + 0xa2, 0x4c, 0xa2, 0x8a, 0xc9, 0x2c, 0xd0, 0xf9, + 0xa5, 0x2a, 0x48, 0x20, 0x56, 0xae, 0x20, 0xf0, + + 0x92, 0xa9, 0x1f, 0x20, 0xee, 0xff, 0x68, 0x20, + 0xee, 0xff, 0x20, 0x56, 0x94, 0x4c, 0x6a, 0x8e, + + 0x20, 0xdd, 0x92, 0x20, 0x8c, 0x8a, 0xc9, 0x29, + 0xd0, 0xda, 0xa5, 0x2a, 0xe5, 0x1e, 0xf0, 0x1a, + + 0xa8, 0xb0, 0x0c, 0x20, 0x25, 0xbc, 0xf0, 0x03, + 0x20, 0xe3, 0x92, 0xa4, 0x2a, 0xf0, 0x0b, 0x20, + + 0x65, 0xb5, 0x88, 0xd0, 0xfa, 0xf0, 0x03, 0x20, + 0x25, 0xbc, 0x18, 0xa4, 0x1b, 0x84, 0x0a, 0x60, + + 0xa6, 0x0b, 0x86, 0x19, 0xa6, 0x0c, 0x86, 0x1a, + 0xa6, 0x0a, 0x86, 0x1b, 0xc9, 0x27, 0xf0, 0xe7, + + 0xc9, 0x8a, 0xf0, 0xbc, 0xc9, 0x89, 0xf0, 0xd0, + 0x38, 0x60, 0x20, 0x97, 0x8a, 0x20, 0x70, 0x8e, + + 0x90, 0xf7, 0xc9, 0x22, 0xf0, 0x11, 0x38, 0x60, + 0x00, 0x09, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6e, + + 0x67, 0x20, 0x22, 0x00, 0x20, 0x58, 0xb5, 0xc8, + 0xb1, 0x19, 0xc9, 0x0d, 0xf0, 0xea, 0xc9, 0x22, + + 0xd0, 0xf2, 0xc8, 0x84, 0x1b, 0xb1, 0x19, 0xc9, + 0x22, 0xd0, 0xaf, 0xf0, 0xe7, 0x20, 0x57, 0x98, + + 0xa9, 0x10, 0xd0, 0x08, 0x20, 0x57, 0x98, 0x20, + 0x28, 0xbc, 0xa9, 0x0c, 0x20, 0xee, 0xff, 0x4c, + + 0x9b, 0x8b, 0x20, 0x1d, 0x9b, 0x20, 0xee, 0x92, + 0x20, 0x94, 0xbd, 0xa0, 0x00, 0x8c, 0x00, 0x06, + + 0x8c, 0xff, 0x06, 0x20, 0x8c, 0x8a, 0xc9, 0x2c, + 0xd0, 0x22, 0xa4, 0x1b, 0x20, 0xd5, 0x95, 0xf0, + + 0x2a, 0xac, 0xff, 0x06, 0xc8, 0xa5, 0x2a, 0x99, + 0x00, 0x06, 0xc8, 0xa5, 0x2b, 0x99, 0x00, 0x06, + + 0xc8, 0xa5, 0x2c, 0x99, 0x00, 0x06, 0xee, 0x00, + 0x06, 0x4c, 0xe0, 0x8e, 0xc6, 0x1b, 0x20, 0x52, + + 0x98, 0x20, 0xea, 0xbd, 0x20, 0x1e, 0x8f, 0xd8, + 0x4c, 0x9b, 0x8b, 0x4c, 0x43, 0xae, 0xad, 0x0c, + + 0x04, 0x4a, 0xad, 0x04, 0x04, 0xae, 0x60, 0x04, + 0xac, 0x64, 0x04, 0x6c, 0x2a, 0x00, 0x4c, 0x2a, + + 0x98, 0x20, 0xdf, 0x97, 0x90, 0xf8, 0x20, 0x94, + 0xbd, 0x20, 0x97, 0x8a, 0xc9, 0x2c, 0xd0, 0xee, + + 0x20, 0xdf, 0x97, 0x90, 0xe9, 0x20, 0x57, 0x98, + 0xa5, 0x2a, 0x85, 0x39, 0xa5, 0x2b, 0x85, 0x3a, + + 0x20, 0xea, 0xbd, 0x20, 0x2d, 0xbc, 0x20, 0x7b, + 0x98, 0x20, 0x22, 0x92, 0xa5, 0x39, 0xc5, 0x2a, + + 0xa5, 0x3a, 0xe5, 0x2b, 0xb0, 0xed, 0x4c, 0xf3, + 0x8a, 0xa9, 0x0a, 0x20, 0xd8, 0xae, 0x20, 0xdf, + + 0x97, 0x20, 0x94, 0xbd, 0xa9, 0x0a, 0x20, 0xd8, + 0xae, 0x20, 0x97, 0x8a, 0xc9, 0x2c, 0xd0, 0x0d, + + 0x20, 0xdf, 0x97, 0xa5, 0x2b, 0xd0, 0x58, 0xa5, + 0x2a, 0xf0, 0x54, 0xe6, 0x0a, 0xc6, 0x0a, 0x4c, + + 0x57, 0x98, 0xa5, 0x12, 0x85, 0x3b, 0xa5, 0x13, + 0x85, 0x3c, 0xa5, 0x18, 0x85, 0x38, 0xa9, 0x01, + + 0x85, 0x37, 0x60, 0x20, 0x69, 0x8f, 0xa2, 0x39, + 0x20, 0x0d, 0xbe, 0x20, 0x6f, 0xbe, 0x20, 0x92, + + 0x8f, 0xa0, 0x00, 0xb1, 0x37, 0x30, 0x30, 0x91, + 0x3b, 0xc8, 0xb1, 0x37, 0x91, 0x3b, 0x38, 0x98, + + 0x65, 0x3b, 0x85, 0x3b, 0xaa, 0xa5, 0x3c, 0x69, + 0x00, 0x85, 0x3c, 0xe4, 0x06, 0xe5, 0x07, 0xb0, + + 0x05, 0x20, 0x9f, 0x90, 0x90, 0xdb, 0x00, 0x00, + 0xcc, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x00, + + 0x00, 0x53, 0x69, 0x6c, 0x6c, 0x79, 0x00, 0x20, + 0x9a, 0x8f, 0xa0, 0x00, 0xb1, 0x37, 0x30, 0x1d, + + 0xa5, 0x3a, 0x91, 0x37, 0xa5, 0x39, 0xc8, 0x91, + 0x37, 0x18, 0xa5, 0x2a, 0x65, 0x39, 0x85, 0x39, + + 0xa9, 0x00, 0x65, 0x3a, 0x29, 0x7f, 0x85, 0x3a, + 0x20, 0x9f, 0x90, 0x90, 0xdd, 0xa5, 0x18, 0x85, + + 0x0c, 0xa0, 0x00, 0x84, 0x0b, 0xc8, 0xb1, 0x0b, + 0x30, 0x20, 0xa0, 0x04, 0xb1, 0x0b, 0xc9, 0x8d, + + 0xf0, 0x1b, 0xc8, 0xc9, 0x0d, 0xd0, 0xf5, 0xb1, + 0x0b, 0x30, 0x0f, 0xa0, 0x03, 0xb1, 0x0b, 0x18, + + 0x65, 0x0b, 0x85, 0x0b, 0x90, 0xe4, 0xe6, 0x0c, + 0xb0, 0xe0, 0x4c, 0xf3, 0x8a, 0x20, 0xeb, 0x97, + + 0x20, 0x92, 0x8f, 0xa0, 0x00, 0xb1, 0x37, 0x30, + 0x37, 0xb1, 0x3b, 0xc8, 0xc5, 0x2b, 0xd0, 0x21, + + 0xb1, 0x3b, 0xc5, 0x2a, 0xd0, 0x1b, 0xb1, 0x37, + 0x85, 0x3d, 0x88, 0xb1, 0x37, 0x85, 0x3e, 0xa4, + + 0x0a, 0x88, 0xa5, 0x0b, 0x85, 0x37, 0xa5, 0x0c, + 0x85, 0x38, 0x20, 0xf5, 0x88, 0xa4, 0x0a, 0xd0, + + 0xab, 0x20, 0x9f, 0x90, 0xa5, 0x3b, 0x69, 0x02, + 0x85, 0x3b, 0x90, 0xc7, 0xe6, 0x3c, 0xb0, 0xc3, + + 0x20, 0xcf, 0xbf, 0x46, 0x61, 0x69, 0x6c, 0x65, + 0x64, 0x20, 0x61, 0x74, 0x20, 0xc8, 0xb1, 0x0b, + + 0x85, 0x2b, 0xc8, 0xb1, 0x0b, 0x85, 0x2a, 0x20, + 0x1f, 0x99, 0x20, 0x25, 0xbc, 0xf0, 0xce, 0xc8, + + 0xb1, 0x37, 0x65, 0x37, 0x85, 0x37, 0x90, 0x03, + 0xe6, 0x38, 0x18, 0x60, 0x20, 0x69, 0x8f, 0xa5, + + 0x2a, 0x48, 0x20, 0xea, 0xbd, 0x20, 0x94, 0xbd, + 0x20, 0x23, 0x99, 0xa9, 0x20, 0x20, 0x02, 0xbc, + + 0x20, 0xea, 0xbd, 0x20, 0x51, 0x89, 0x20, 0x8d, + 0xbc, 0x20, 0x20, 0xbd, 0x68, 0x48, 0x18, 0x65, + + 0x2a, 0x85, 0x2a, 0x90, 0xe0, 0xe6, 0x2b, 0x10, + 0xdc, 0x4c, 0xf3, 0x8a, 0x4c, 0x18, 0x92, 0xc6, + + 0x0a, 0x20, 0x82, 0x95, 0xf0, 0x41, 0xb0, 0x3f, + 0x20, 0x94, 0xbd, 0x20, 0xdd, 0x92, 0x20, 0x22, + + 0x92, 0xa5, 0x2d, 0x05, 0x2c, 0xd0, 0x30, 0x18, + 0xa5, 0x2a, 0x65, 0x02, 0xa8, 0xa5, 0x2b, 0x65, + + 0x03, 0xaa, 0xc4, 0x04, 0xe5, 0x05, 0xb0, 0xd4, + 0xa5, 0x02, 0x85, 0x2a, 0xa5, 0x03, 0x85, 0x2b, + + 0x84, 0x02, 0x86, 0x03, 0xa9, 0x00, 0x85, 0x2c, + 0x85, 0x2d, 0xa9, 0x40, 0x85, 0x27, 0x20, 0xb4, + + 0xb4, 0x20, 0x27, 0x88, 0x4c, 0x0b, 0x92, 0x00, + 0x0a, 0x42, 0x61, 0x64, 0x20, 0xde, 0x00, 0x20, + + 0x97, 0x8a, 0x98, 0x18, 0x65, 0x0b, 0xa6, 0x0c, + 0x90, 0x02, 0xe8, 0x18, 0xe9, 0x00, 0x85, 0x37, + + 0x8a, 0xe9, 0x00, 0x85, 0x38, 0xa2, 0x05, 0x86, + 0x3f, 0xa6, 0x0a, 0x20, 0x59, 0x95, 0xc0, 0x01, + + 0xf0, 0xd5, 0xc9, 0x28, 0xf0, 0x15, 0xc9, 0x24, + 0xf0, 0x04, 0xc9, 0x25, 0xd0, 0x0a, 0xc6, 0x3f, + + 0xc8, 0xe8, 0xb1, 0x37, 0xc9, 0x28, 0xf0, 0x03, + 0x4c, 0xdf, 0x90, 0x84, 0x39, 0x86, 0x0a, 0x20, + + 0x69, 0x94, 0xd0, 0xb3, 0x20, 0xfc, 0x94, 0xa2, + 0x01, 0x20, 0x31, 0x95, 0xa5, 0x3f, 0x48, 0xa9, + + 0x01, 0x48, 0x20, 0xd8, 0xae, 0x20, 0x94, 0xbd, + 0x20, 0x21, 0x88, 0xa5, 0x2b, 0x29, 0xc0, 0x05, + + 0x2c, 0x05, 0x2d, 0xd0, 0x92, 0x20, 0x22, 0x92, + 0x68, 0xa8, 0xa5, 0x2a, 0x91, 0x02, 0xc8, 0xa5, + + 0x2b, 0x91, 0x02, 0xc8, 0x98, 0x48, 0x20, 0x31, + 0x92, 0x20, 0x97, 0x8a, 0xc9, 0x2c, 0xf0, 0xd5, + + 0xc9, 0x29, 0xf0, 0x03, 0x4c, 0x27, 0x91, 0x68, + 0x85, 0x15, 0x68, 0x85, 0x3f, 0xa9, 0x00, 0x85, + + 0x40, 0x20, 0x36, 0x92, 0xa0, 0x00, 0xa5, 0x15, + 0x91, 0x02, 0x65, 0x2a, 0x85, 0x2a, 0x90, 0x02, + + 0xe6, 0x2b, 0xa5, 0x03, 0x85, 0x38, 0xa5, 0x02, + 0x85, 0x37, 0x18, 0x65, 0x2a, 0xa8, 0xa5, 0x2b, + + 0x65, 0x03, 0xb0, 0x34, 0xaa, 0xc4, 0x04, 0xe5, + 0x05, 0xb0, 0x2d, 0x84, 0x02, 0x86, 0x03, 0xa5, + + 0x37, 0x65, 0x15, 0xa8, 0xa9, 0x00, 0x85, 0x37, + 0x90, 0x02, 0xe6, 0x38, 0x91, 0x37, 0xc8, 0xd0, + + 0x02, 0xe6, 0x38, 0xc4, 0x02, 0xd0, 0xf5, 0xe4, + 0x38, 0xd0, 0xf1, 0x20, 0x97, 0x8a, 0xc9, 0x2c, + + 0xf0, 0x03, 0x4c, 0x96, 0x8b, 0x4c, 0x2f, 0x91, + 0x00, 0x0b, 0xde, 0x20, 0x73, 0x70, 0x61, 0x63, + + 0x65, 0x00, 0xe6, 0x2a, 0xd0, 0x0a, 0xe6, 0x2b, + 0xd0, 0x06, 0xe6, 0x2c, 0xd0, 0x02, 0xe6, 0x2d, + + 0x60, 0xa2, 0x3f, 0x20, 0x0d, 0xbe, 0xa2, 0x00, + 0xa0, 0x00, 0x46, 0x40, 0x66, 0x3f, 0x90, 0x0b, + + 0x18, 0x98, 0x65, 0x2a, 0xa8, 0x8a, 0x65, 0x2b, + 0xaa, 0xb0, 0x0f, 0x06, 0x2a, 0x26, 0x2b, 0xa5, + + 0x3f, 0x05, 0x40, 0xd0, 0xe5, 0x84, 0x2a, 0x86, + 0x2b, 0x60, 0x4c, 0x27, 0x91, 0x20, 0xeb, 0x92, + + 0xa5, 0x2a, 0x85, 0x06, 0x85, 0x04, 0xa5, 0x2b, + 0x85, 0x07, 0x85, 0x05, 0x4c, 0x9b, 0x8b, 0x20, + + 0xeb, 0x92, 0xa5, 0x2a, 0x85, 0x00, 0x85, 0x02, + 0xa5, 0x2b, 0x85, 0x01, 0x85, 0x03, 0x20, 0x2f, + + 0xbd, 0xf0, 0x07, 0x20, 0xeb, 0x92, 0xa5, 0x2b, + 0x85, 0x18, 0x4c, 0x9b, 0x8b, 0x20, 0x57, 0x98, + + 0x20, 0x20, 0xbd, 0xf0, 0xf5, 0x20, 0xdf, 0x97, + 0xb0, 0x0b, 0xc9, 0xee, 0xf0, 0x19, 0xc9, 0x87, + + 0xf0, 0x1e, 0x20, 0x21, 0x88, 0x20, 0x57, 0x98, + 0xa5, 0x2a, 0x85, 0x21, 0xa5, 0x2b, 0x85, 0x22, + + 0xa9, 0xff, 0x85, 0x20, 0x4c, 0x9b, 0x8b, 0xe6, + 0x0a, 0x20, 0x57, 0x98, 0xa9, 0xff, 0xd0, 0xee, + + 0xe6, 0x0a, 0x20, 0x57, 0x98, 0xa9, 0x00, 0xf0, + 0xe9, 0x20, 0xeb, 0x92, 0xa2, 0x2a, 0xa0, 0x00, + + 0x84, 0x2e, 0xa9, 0x02, 0x20, 0xf1, 0xff, 0x4c, + 0x9b, 0x8b, 0x20, 0xae, 0x8a, 0x20, 0x29, 0x9b, + + 0x4c, 0xf0, 0x92, 0x20, 0xec, 0xad, 0xf0, 0x0f, + 0x30, 0x0a, 0x60, 0x20, 0x07, 0x98, 0xa5, 0x27, + + 0xf0, 0x05, 0x10, 0xf6, 0x4c, 0xe4, 0xa3, 0x4c, + 0x0e, 0x8c, 0x20, 0xec, 0xad, 0xf0, 0xf8, 0x30, + + 0xe9, 0x4c, 0xbe, 0xa2, 0xa5, 0x0b, 0x85, 0x19, + 0xa5, 0x0c, 0x85, 0x1a, 0xa5, 0x0a, 0x85, 0x1b, + + 0xa9, 0xf2, 0x20, 0x97, 0xb1, 0x20, 0x52, 0x98, + 0x4c, 0x9b, 0x8b, 0xa0, 0x03, 0xa9, 0x00, 0x91, + + 0x2a, 0xf0, 0x1e, 0xba, 0xe0, 0xfc, 0xb0, 0x43, + 0x20, 0x82, 0x95, 0xf0, 0x26, 0x20, 0x0d, 0xb3, + + 0xa4, 0x2c, 0x30, 0xe7, 0x20, 0x94, 0xbd, 0xa9, + 0x00, 0x20, 0xd8, 0xae, 0x85, 0x27, 0x20, 0xb4, + + 0xb4, 0xba, 0xfe, 0x06, 0x01, 0xa4, 0x1b, 0x84, + 0x0a, 0x20, 0x97, 0x8a, 0xc9, 0x2c, 0xf0, 0xd3, + + 0x4c, 0x96, 0x8b, 0x4c, 0x98, 0x8b, 0xba, 0xe0, + 0xfc, 0xb0, 0x0a, 0xad, 0xff, 0x01, 0xc9, 0xf2, + + 0xd0, 0x03, 0x4c, 0x57, 0x98, 0x00, 0x0d, 0x4e, + 0x6f, 0x20, 0xf2, 0x00, 0x0c, 0x4e, 0x6f, 0x74, + + 0x20, 0xea, 0x00, 0x19, 0x42, 0x61, 0x64, 0x20, + 0xeb, 0x00, 0x20, 0x21, 0x88, 0xa5, 0x2a, 0x48, + + 0x20, 0xda, 0x92, 0x20, 0x52, 0x98, 0xa9, 0x12, + 0x20, 0xee, 0xff, 0x4c, 0xda, 0x93, 0xa9, 0x11, + + 0x48, 0x20, 0x21, 0x88, 0x20, 0x57, 0x98, 0x4c, + 0xda, 0x93, 0xa9, 0x16, 0x48, 0x20, 0x21, 0x88, + + 0x20, 0x57, 0x98, 0x20, 0xe7, 0xbe, 0xe0, 0xff, + 0xd0, 0x2d, 0xc0, 0xff, 0xd0, 0x29, 0xa5, 0x04, + + 0xc5, 0x06, 0xd0, 0xbe, 0xa5, 0x05, 0xc5, 0x07, + 0xd0, 0xb8, 0xa6, 0x2a, 0xa9, 0x85, 0x20, 0xf4, + + 0xff, 0xe4, 0x02, 0x98, 0xe5, 0x03, 0x90, 0xaa, + 0xe4, 0x12, 0x98, 0xe5, 0x13, 0x90, 0xa3, 0x86, + + 0x06, 0x86, 0x04, 0x84, 0x07, 0x84, 0x05, 0x20, + 0x28, 0xbc, 0x68, 0x20, 0xee, 0xff, 0x20, 0x56, + + 0x94, 0x4c, 0x9b, 0x8b, 0xa9, 0x04, 0xd0, 0x02, + 0xa9, 0x05, 0x48, 0x20, 0x1d, 0x9b, 0x4c, 0xfd, + + 0x93, 0x20, 0x21, 0x88, 0xa5, 0x2a, 0x48, 0x20, + 0xae, 0x8a, 0x20, 0x29, 0x9b, 0x20, 0xee, 0x92, + + 0x20, 0x94, 0xbd, 0x20, 0xda, 0x92, 0x20, 0x52, + 0x98, 0xa9, 0x19, 0x20, 0xee, 0xff, 0x68, 0x20, + + 0xee, 0xff, 0x20, 0x0b, 0xbe, 0xa5, 0x37, 0x20, + 0xee, 0xff, 0xa5, 0x38, 0x20, 0xee, 0xff, 0x20, + + 0x56, 0x94, 0xa5, 0x2b, 0x20, 0xee, 0xff, 0x4c, + 0x9b, 0x8b, 0xa5, 0x2b, 0x20, 0xee, 0xff, 0x20, + + 0x97, 0x8a, 0xc9, 0x3a, 0xf0, 0x1d, 0xc9, 0x0d, + 0xf0, 0x19, 0xc9, 0x8b, 0xf0, 0x15, 0xc6, 0x0a, + + 0x20, 0x21, 0x88, 0x20, 0x56, 0x94, 0x20, 0x97, + 0x8a, 0xc9, 0x2c, 0xf0, 0xe2, 0xc9, 0x3b, 0xd0, + + 0xe1, 0xf0, 0xd7, 0x4c, 0x96, 0x8b, 0xa5, 0x2a, + 0x6c, 0x0e, 0x02, 0xa0, 0x01, 0xb1, 0x37, 0xa0, + + 0xf6, 0xc9, 0xf2, 0xf0, 0x0a, 0xa0, 0xf8, 0xd0, + 0x06, 0xa0, 0x01, 0xb1, 0x37, 0x0a, 0xa8, 0xb9, + + 0x00, 0x04, 0x85, 0x3a, 0xb9, 0x01, 0x04, 0x85, + 0x3b, 0xa5, 0x3b, 0xf0, 0x35, 0xa0, 0x00, 0xb1, + + 0x3a, 0x85, 0x3c, 0xc8, 0xb1, 0x3a, 0x85, 0x3d, + 0xc8, 0xb1, 0x3a, 0xd0, 0x0d, 0x88, 0xc4, 0x39, + + 0xd0, 0x21, 0xc8, 0xb0, 0x12, 0xc8, 0xb1, 0x3a, + 0xf0, 0x19, 0xd1, 0x37, 0xd0, 0x15, 0xc4, 0x39, + + 0xd0, 0xf3, 0xc8, 0xb1, 0x3a, 0xd0, 0x0c, 0x98, + 0x65, 0x3a, 0x85, 0x2a, 0xa5, 0x3b, 0x69, 0x00, + + 0x85, 0x2b, 0x60, 0xa5, 0x3d, 0xf0, 0xfb, 0xa0, + 0x00, 0xb1, 0x3c, 0x85, 0x3a, 0xc8, 0xb1, 0x3c, + + 0x85, 0x3b, 0xc8, 0xb1, 0x3c, 0xd0, 0x0d, 0x88, + 0xc4, 0x39, 0xd0, 0xad, 0xc8, 0xb0, 0x12, 0xc8, + + 0xb1, 0x3c, 0xf0, 0xa5, 0xd1, 0x37, 0xd0, 0xa1, + 0xc4, 0x39, 0xd0, 0xf3, 0xc8, 0xb1, 0x3c, 0xd0, + + 0x98, 0x98, 0x65, 0x3c, 0x85, 0x2a, 0xa5, 0x3d, + 0x69, 0x00, 0x85, 0x2b, 0x60, 0xa0, 0x01, 0xb1, + + 0x37, 0xaa, 0xa9, 0xf6, 0xe0, 0xf2, 0xf0, 0x09, + 0xa9, 0xf8, 0xd0, 0x05, 0xa0, 0x01, 0xb1, 0x37, + + 0x0a, 0x85, 0x3a, 0xa9, 0x04, 0x85, 0x3b, 0xb1, + 0x3a, 0xf0, 0x0b, 0xaa, 0x88, 0xb1, 0x3a, 0x85, + + 0x3a, 0x86, 0x3b, 0xc8, 0x10, 0xf1, 0xa5, 0x03, + 0x91, 0x3a, 0xa5, 0x02, 0x88, 0x91, 0x3a, 0x98, + + 0xc8, 0x91, 0x02, 0xc4, 0x39, 0xf0, 0x31, 0xc8, + 0xb1, 0x37, 0x91, 0x02, 0xc4, 0x39, 0xd0, 0xf7, + + 0x60, 0xa9, 0x00, 0xc8, 0x91, 0x02, 0xca, 0xd0, + 0xfa, 0x38, 0x98, 0x65, 0x02, 0x90, 0x02, 0xe6, + + 0x03, 0xa4, 0x03, 0xc4, 0x05, 0x90, 0x0f, 0xd0, + 0x04, 0xc5, 0x04, 0x90, 0x09, 0xa9, 0x00, 0xa0, + + 0x01, 0x91, 0x3a, 0x4c, 0xb7, 0x8c, 0x85, 0x02, + 0x60, 0xa0, 0x01, 0xb1, 0x37, 0xc9, 0x30, 0x90, + + 0x18, 0xc9, 0x40, 0xb0, 0x0c, 0xc9, 0x3a, 0xb0, + 0x10, 0xc0, 0x01, 0xf0, 0x0c, 0xe8, 0xc8, 0xd0, + + 0xea, 0xc9, 0x5f, 0xb0, 0x05, 0xc9, 0x5b, 0x90, + 0xf4, 0x60, 0xc9, 0x7b, 0x90, 0xef, 0x60, 0x20, + + 0x31, 0x95, 0x20, 0xc9, 0x95, 0xd0, 0x1d, 0xb0, + 0x1b, 0x20, 0xfc, 0x94, 0xa2, 0x05, 0xe4, 0x2c, + + 0xd0, 0xed, 0xe8, 0xd0, 0xea, 0xc9, 0x21, 0xf0, + 0x0c, 0xc9, 0x24, 0xf0, 0x13, 0x49, 0x3f, 0xf0, + + 0x06, 0xa9, 0x00, 0x38, 0x60, 0xa9, 0x04, 0x48, + 0xe6, 0x1b, 0x20, 0xe3, 0x92, 0x4c, 0x9f, 0x96, + + 0xe6, 0x1b, 0x20, 0xe3, 0x92, 0xa5, 0x2b, 0xf0, + 0x06, 0xa9, 0x80, 0x85, 0x2c, 0x38, 0x60, 0x00, + + 0x08, 0x24, 0x20, 0x72, 0x61, 0x6e, 0x67, 0x65, + 0x00, 0xa5, 0x0b, 0x85, 0x19, 0xa5, 0x0c, 0x85, + + 0x1a, 0xa4, 0x0a, 0x88, 0xc8, 0x84, 0x1b, 0xb1, + 0x19, 0xc9, 0x20, 0xf0, 0xf7, 0xc9, 0x40, 0x90, + + 0xb4, 0xc9, 0x5b, 0xb0, 0x1a, 0x0a, 0x0a, 0x85, + 0x2a, 0xa9, 0x04, 0x85, 0x2b, 0xc8, 0xb1, 0x19, + + 0xc8, 0xc9, 0x25, 0xd0, 0x0a, 0xa2, 0x04, 0x86, + 0x2c, 0xb1, 0x19, 0xc9, 0x28, 0xd0, 0x66, 0xa2, + + 0x05, 0x86, 0x2c, 0xa5, 0x1b, 0x18, 0x65, 0x19, + 0xa6, 0x1a, 0x90, 0x02, 0xe8, 0x18, 0xe9, 0x00, + + 0x85, 0x37, 0xb0, 0x01, 0xca, 0x86, 0x38, 0xa6, + 0x1b, 0xa0, 0x01, 0xb1, 0x37, 0xc9, 0x41, 0xb0, + + 0x0c, 0xc9, 0x30, 0x90, 0x1c, 0xc9, 0x3a, 0xb0, + 0x18, 0xe8, 0xc8, 0xd0, 0xee, 0xc9, 0x5b, 0xb0, + + 0x04, 0xe8, 0xc8, 0xd0, 0xe6, 0xc9, 0x5f, 0x90, + 0x08, 0xc9, 0x7b, 0xb0, 0x04, 0xe8, 0xc8, 0xd0, + + 0xda, 0x88, 0xf0, 0x2f, 0xc9, 0x24, 0xf0, 0x67, + 0xc9, 0x25, 0xd0, 0x08, 0xc6, 0x2c, 0xc8, 0xe8, + + 0xc8, 0xb1, 0x37, 0x88, 0x84, 0x39, 0xc9, 0x28, + 0xf0, 0x4c, 0x20, 0x69, 0x94, 0xf0, 0x18, 0x86, + + 0x1b, 0xa4, 0x1b, 0xb1, 0x19, 0xc9, 0x21, 0xf0, + 0x16, 0xc9, 0x3f, 0xf0, 0x0e, 0x18, 0x84, 0x1b, + + 0xa9, 0xff, 0x60, 0xa9, 0x00, 0x38, 0x60, 0xa9, + 0x00, 0x18, 0x60, 0xa9, 0x00, 0xf0, 0x02, 0xa9, + + 0x04, 0x48, 0xc8, 0x84, 0x1b, 0x20, 0x2c, 0xb3, + 0x20, 0xf0, 0x92, 0xa5, 0x2b, 0x48, 0xa5, 0x2a, + + 0x48, 0x20, 0xe3, 0x92, 0x18, 0x68, 0x65, 0x2a, + 0x85, 0x2a, 0x68, 0x65, 0x2b, 0x85, 0x2b, 0x68, + + 0x85, 0x2c, 0x18, 0xa9, 0xff, 0x60, 0xe8, 0xe6, + 0x39, 0x20, 0xdf, 0x96, 0x4c, 0x61, 0x96, 0xe8, + + 0xc8, 0x84, 0x39, 0xc8, 0xc6, 0x2c, 0xb1, 0x37, + 0xc9, 0x28, 0xf0, 0x0d, 0x20, 0x69, 0x94, 0xf0, + + 0xb6, 0x86, 0x1b, 0xa9, 0x81, 0x85, 0x2c, 0x38, + 0x60, 0xe8, 0x84, 0x39, 0xc6, 0x2c, 0x20, 0xdf, + + 0x96, 0xa9, 0x81, 0x85, 0x2c, 0x38, 0x60, 0x00, + 0x0e, 0x41, 0x72, 0x72, 0x61, 0x79, 0x00, 0x20, + + 0x69, 0x94, 0xf0, 0xf3, 0x86, 0x1b, 0xa5, 0x2c, + 0x48, 0xa5, 0x2a, 0x48, 0xa5, 0x2b, 0x48, 0xa0, + + 0x00, 0xb1, 0x2a, 0xc9, 0x04, 0x90, 0x75, 0x98, + 0x20, 0xd8, 0xae, 0xa9, 0x01, 0x85, 0x2d, 0x20, + + 0x94, 0xbd, 0x20, 0xdd, 0x92, 0xe6, 0x1b, 0xe0, + 0x2c, 0xd0, 0xcc, 0xa2, 0x39, 0x20, 0x0d, 0xbe, + + 0xa4, 0x3c, 0x68, 0x85, 0x38, 0x68, 0x85, 0x37, + 0x48, 0xa5, 0x38, 0x48, 0x20, 0xba, 0x97, 0x84, + + 0x2d, 0xb1, 0x37, 0x85, 0x3f, 0xc8, 0xb1, 0x37, + 0x85, 0x40, 0xa5, 0x2a, 0x65, 0x39, 0x85, 0x2a, + + 0xa5, 0x2b, 0x65, 0x3a, 0x85, 0x2b, 0x20, 0x36, + 0x92, 0xa0, 0x00, 0x38, 0xb1, 0x37, 0xe5, 0x2d, + + 0xc9, 0x03, 0xb0, 0xbb, 0x20, 0x94, 0xbd, 0x20, + 0x56, 0xae, 0x20, 0xf0, 0x92, 0x68, 0x85, 0x38, + + 0x68, 0x85, 0x37, 0xa2, 0x39, 0x20, 0x0d, 0xbe, + 0xa4, 0x3c, 0x20, 0xba, 0x97, 0x18, 0xa5, 0x39, + + 0x65, 0x2a, 0x85, 0x2a, 0xa5, 0x3a, 0x65, 0x2b, + 0x85, 0x2b, 0x90, 0x11, 0x20, 0x56, 0xae, 0x20, + + 0xf0, 0x92, 0x68, 0x85, 0x38, 0x68, 0x85, 0x37, + 0xa0, 0x01, 0x20, 0xba, 0x97, 0x68, 0x85, 0x2c, + + 0xc9, 0x05, 0xd0, 0x17, 0xa6, 0x2b, 0xa5, 0x2a, + 0x06, 0x2a, 0x26, 0x2b, 0x06, 0x2a, 0x26, 0x2b, + + 0x65, 0x2a, 0x85, 0x2a, 0x8a, 0x65, 0x2b, 0x85, + 0x2b, 0x90, 0x08, 0x06, 0x2a, 0x26, 0x2b, 0x06, + + 0x2a, 0x26, 0x2b, 0x98, 0x65, 0x2a, 0x85, 0x2a, + 0x90, 0x03, 0xe6, 0x2b, 0x18, 0xa5, 0x37, 0x65, + + 0x2a, 0x85, 0x2a, 0xa5, 0x38, 0x65, 0x2b, 0x85, + 0x2b, 0x60, 0xa5, 0x2b, 0x29, 0xc0, 0x05, 0x2c, + + 0x05, 0x2d, 0xd0, 0x0d, 0xa5, 0x2a, 0xd1, 0x37, + 0xc8, 0xa5, 0x2b, 0xf1, 0x37, 0xb0, 0x02, 0xc8, + + 0x60, 0x00, 0x0f, 0x53, 0x75, 0x62, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x00, 0xe6, 0x0a, 0xa4, + + 0x0a, 0xb1, 0x0b, 0xc9, 0x20, 0xf0, 0xf6, 0xc9, + 0x8d, 0xd0, 0x1a, 0xc8, 0xb1, 0x0b, 0x0a, 0x0a, + + 0xaa, 0x29, 0xc0, 0xc8, 0x51, 0x0b, 0x85, 0x2a, + 0x8a, 0x0a, 0x0a, 0xc8, 0x51, 0x0b, 0x85, 0x2b, + + 0xc8, 0x84, 0x0a, 0x38, 0x60, 0x18, 0x60, 0xa5, + 0x0b, 0x85, 0x19, 0xa5, 0x0c, 0x85, 0x1a, 0xa5, + + 0x0a, 0x85, 0x1b, 0xa4, 0x1b, 0xe6, 0x1b, 0xb1, + 0x19, 0xc9, 0x20, 0xf0, 0xf6, 0xc9, 0x3d, 0xf0, + + 0x28, 0x00, 0x04, 0x4d, 0x69, 0x73, 0x74, 0x61, + 0x6b, 0x65, 0x00, 0x10, 0x53, 0x79, 0x6e, 0x74, + + 0x61, 0x78, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, + 0x00, 0x11, 0x45, 0x73, 0x63, 0x61, 0x70, 0x65, + + 0x00, 0x20, 0x8c, 0x8a, 0xc9, 0x3d, 0xd0, 0xd9, + 0x60, 0x20, 0x29, 0x9b, 0x8a, 0xa4, 0x1b, 0x4c, + + 0x61, 0x98, 0xa4, 0x1b, 0x4c, 0x59, 0x98, 0xa4, + 0x0a, 0x88, 0xc8, 0xb1, 0x0b, 0xc9, 0x20, 0xf0, + + 0xf9, 0xc9, 0x3a, 0xf0, 0x08, 0xc9, 0x0d, 0xf0, + 0x04, 0xc9, 0x8b, 0xd0, 0xbd, 0x18, 0x98, 0x65, + + 0x0b, 0x85, 0x0b, 0x90, 0x02, 0xe6, 0x0c, 0xa0, + 0x01, 0x84, 0x0a, 0x24, 0xff, 0x30, 0xb9, 0x60, + + 0x20, 0x57, 0x98, 0x88, 0xb1, 0x0b, 0xc9, 0x3a, + 0xf0, 0xf5, 0xa5, 0x0c, 0xc9, 0x07, 0xf0, 0x2c, + + 0xc8, 0xb1, 0x0b, 0x30, 0x27, 0xa5, 0x20, 0xf0, + 0x13, 0x98, 0x48, 0xc8, 0xb1, 0x0b, 0x48, 0x88, + + 0xb1, 0x0b, 0xa8, 0x68, 0x20, 0xea, 0xae, 0x20, + 0x05, 0x99, 0x68, 0xa8, 0xc8, 0x38, 0x98, 0x65, + + 0x0b, 0x85, 0x0b, 0x90, 0x02, 0xe6, 0x0c, 0xa0, + 0x01, 0x84, 0x0a, 0x60, 0x4c, 0xf6, 0x8a, 0x4c, + + 0x0e, 0x8c, 0x20, 0x1d, 0x9b, 0xf0, 0xf8, 0x10, + 0x03, 0x20, 0xe4, 0xa3, 0xa4, 0x1b, 0x84, 0x0a, + + 0xa5, 0x2a, 0x05, 0x2b, 0x05, 0x2c, 0x05, 0x2d, + 0xf0, 0x17, 0xe0, 0x8c, 0xf0, 0x03, 0x4c, 0xa3, + + 0x8b, 0xe6, 0x0a, 0x20, 0xdf, 0x97, 0x90, 0xf6, + 0x20, 0xaf, 0xb9, 0x20, 0x77, 0x98, 0x4c, 0xd2, + + 0xb8, 0xa4, 0x0a, 0xb1, 0x0b, 0xc9, 0x0d, 0xf0, + 0x09, 0xc8, 0xc9, 0x8b, 0xd0, 0xf5, 0x84, 0x0a, + + 0xf0, 0xe1, 0x4c, 0x87, 0x8b, 0xa5, 0x2a, 0xc5, + 0x21, 0xa5, 0x2b, 0xe5, 0x22, 0xb0, 0xac, 0xa9, + + 0x5b, 0x20, 0x58, 0xb5, 0x20, 0x1f, 0x99, 0xa9, + 0x5d, 0x20, 0x58, 0xb5, 0x4c, 0x65, 0xb5, 0xa9, + + 0x00, 0xf0, 0x02, 0xa9, 0x05, 0x85, 0x14, 0xa2, + 0x04, 0xa9, 0x00, 0x95, 0x3f, 0x38, 0xa5, 0x2a, + + 0xfd, 0x6b, 0x99, 0xa8, 0xa5, 0x2b, 0xfd, 0xb9, + 0x99, 0x90, 0x08, 0x85, 0x2b, 0x84, 0x2a, 0xf6, + + 0x3f, 0xd0, 0xeb, 0xca, 0x10, 0xe3, 0xa2, 0x05, + 0xca, 0xf0, 0x04, 0xb5, 0x3f, 0xf0, 0xf9, 0x86, + + 0x37, 0xa5, 0x14, 0xf0, 0x0b, 0xe5, 0x37, 0xf0, + 0x07, 0xa8, 0x20, 0x65, 0xb5, 0x88, 0xd0, 0xfa, + + 0xb5, 0x3f, 0x09, 0x30, 0x20, 0x58, 0xb5, 0xca, + 0x10, 0xf6, 0x60, 0x01, 0x0a, 0x64, 0xe8, 0x10, + + 0xa0, 0x00, 0x84, 0x3d, 0xa5, 0x18, 0x85, 0x3e, + 0xa0, 0x01, 0xb1, 0x3d, 0xc5, 0x2b, 0xb0, 0x0e, + + 0xa0, 0x03, 0xb1, 0x3d, 0x65, 0x3d, 0x85, 0x3d, + 0x90, 0xee, 0xe6, 0x3e, 0xb0, 0xea, 0xd0, 0x14, + + 0xa0, 0x02, 0xb1, 0x3d, 0xc5, 0x2a, 0x90, 0xe8, + 0xd0, 0x0a, 0x98, 0x65, 0x3d, 0x85, 0x3d, 0x90, + + 0x03, 0xe6, 0x3e, 0x18, 0xa0, 0x02, 0x60, 0x00, + 0x12, 0x44, 0x69, 0x76, 0x69, 0x73, 0x69, 0x6f, + + 0x6e, 0x20, 0x62, 0x79, 0x20, 0x7a, 0x65, 0x72, + 0x6f, 0x00, 0x00, 0x00, 0x03, 0x27, 0xa8, 0x20, + + 0xf0, 0x92, 0xa5, 0x2d, 0x48, 0x20, 0x71, 0xad, + 0x20, 0x1d, 0x9e, 0x86, 0x27, 0xa8, 0x20, 0xf0, + + 0x92, 0x68, 0x85, 0x38, 0x45, 0x2d, 0x85, 0x37, + 0x20, 0x71, 0xad, 0xa2, 0x39, 0x20, 0x0d, 0xbe, + + 0x84, 0x3d, 0x84, 0x3e, 0x84, 0x3f, 0x84, 0x40, + 0xa5, 0x2d, 0x05, 0x2a, 0x05, 0x2b, 0x05, 0x2c, + + 0xf0, 0xb5, 0xa0, 0x20, 0x88, 0xf0, 0x41, 0x06, + 0x39, 0x26, 0x3a, 0x26, 0x3b, 0x26, 0x3c, 0x10, + + 0xf3, 0x26, 0x39, 0x26, 0x3a, 0x26, 0x3b, 0x26, + 0x3c, 0x26, 0x3d, 0x26, 0x3e, 0x26, 0x3f, 0x26, + + 0x40, 0x38, 0xa5, 0x3d, 0xe5, 0x2a, 0x48, 0xa5, + 0x3e, 0xe5, 0x2b, 0x48, 0xa5, 0x3f, 0xe5, 0x2c, + + 0xaa, 0xa5, 0x40, 0xe5, 0x2d, 0x90, 0x0c, 0x85, + 0x40, 0x86, 0x3f, 0x68, 0x85, 0x3e, 0x68, 0x85, + + 0x3d, 0xb0, 0x02, 0x68, 0x68, 0x88, 0xd0, 0xc9, + 0x60, 0x86, 0x27, 0x20, 0xea, 0xbd, 0x20, 0x51, + + 0xbd, 0x20, 0xbe, 0xa2, 0x20, 0x1e, 0xa2, 0x20, + 0x7e, 0xbd, 0x20, 0xb5, 0xa3, 0x4c, 0x62, 0x9a, + + 0x20, 0x51, 0xbd, 0x20, 0x42, 0x9c, 0x86, 0x27, + 0xa8, 0x20, 0xfd, 0x92, 0x20, 0x7e, 0xbd, 0x20, + + 0x4e, 0xa3, 0xa6, 0x27, 0xa0, 0x00, 0xa5, 0x3b, + 0x29, 0x80, 0x85, 0x3b, 0xa5, 0x2e, 0x29, 0x80, + + 0xc5, 0x3b, 0xd0, 0x1e, 0xa5, 0x3d, 0xc5, 0x30, + 0xd0, 0x19, 0xa5, 0x3e, 0xc5, 0x31, 0xd0, 0x13, + + 0xa5, 0x3f, 0xc5, 0x32, 0xd0, 0x0d, 0xa5, 0x40, + 0xc5, 0x33, 0xd0, 0x07, 0xa5, 0x41, 0xc5, 0x34, + + 0xd0, 0x01, 0x60, 0x6a, 0x45, 0x3b, 0x2a, 0xa9, + 0x01, 0x60, 0x4c, 0x0e, 0x8c, 0x8a, 0xf0, 0x47, + + 0x30, 0xae, 0x20, 0x94, 0xbd, 0x20, 0x42, 0x9c, + 0xa8, 0xf0, 0xef, 0x30, 0x8c, 0xa5, 0x2d, 0x49, + + 0x80, 0x85, 0x2d, 0x38, 0xa0, 0x00, 0xb1, 0x04, + 0xe5, 0x2a, 0x85, 0x2a, 0xc8, 0xb1, 0x04, 0xe5, + + 0x2b, 0x85, 0x2b, 0xc8, 0xb1, 0x04, 0xe5, 0x2c, + 0x85, 0x2c, 0xc8, 0xb1, 0x04, 0xa0, 0x00, 0x49, + + 0x80, 0xe5, 0x2d, 0x05, 0x2a, 0x05, 0x2b, 0x05, + 0x2c, 0x08, 0x18, 0xa9, 0x04, 0x65, 0x04, 0x85, + + 0x04, 0x90, 0x02, 0xe6, 0x05, 0x28, 0x60, 0x20, + 0xb2, 0xbd, 0x20, 0x42, 0x9c, 0xa8, 0xd0, 0xaa, + + 0x86, 0x37, 0xa6, 0x36, 0xa0, 0x00, 0xb1, 0x04, + 0x85, 0x39, 0xc5, 0x36, 0xb0, 0x01, 0xaa, 0x86, + + 0x3a, 0xa0, 0x00, 0xc4, 0x3a, 0xf0, 0x0a, 0xc8, + 0xb1, 0x04, 0xd9, 0xff, 0x05, 0xf0, 0xf4, 0xd0, + + 0x04, 0xa5, 0x39, 0xc5, 0x36, 0x08, 0x20, 0xdc, + 0xbd, 0xa6, 0x37, 0x28, 0x60, 0xa5, 0x0b, 0x85, + + 0x19, 0xa5, 0x0c, 0x85, 0x1a, 0xa5, 0x0a, 0x85, + 0x1b, 0x20, 0x72, 0x9b, 0xe0, 0x84, 0xf0, 0x0a, + + 0xe0, 0x82, 0xf0, 0x21, 0xc6, 0x1b, 0xa8, 0x85, + 0x27, 0x60, 0x20, 0x6b, 0x9b, 0xa8, 0x20, 0xf0, + + 0x92, 0xa0, 0x03, 0xb1, 0x04, 0x19, 0x2a, 0x00, + 0x99, 0x2a, 0x00, 0x88, 0x10, 0xf5, 0x20, 0xff, + + 0xbd, 0xa9, 0x40, 0xd0, 0xd7, 0x20, 0x6b, 0x9b, + 0xa8, 0x20, 0xf0, 0x92, 0xa0, 0x03, 0xb1, 0x04, + + 0x59, 0x2a, 0x00, 0x99, 0x2a, 0x00, 0x88, 0x10, + 0xf5, 0x30, 0xe3, 0xa8, 0x20, 0xf0, 0x92, 0x20, + + 0x94, 0xbd, 0x20, 0x9c, 0x9b, 0xe0, 0x80, 0xf0, + 0x01, 0x60, 0xa8, 0x20, 0xf0, 0x92, 0x20, 0x94, + + 0xbd, 0x20, 0x9c, 0x9b, 0xa8, 0x20, 0xf0, 0x92, + 0xa0, 0x03, 0xb1, 0x04, 0x39, 0x2a, 0x00, 0x99, + + 0x2a, 0x00, 0x88, 0x10, 0xf5, 0x20, 0xff, 0xbd, + 0xa9, 0x40, 0xd0, 0xd9, 0x20, 0x42, 0x9c, 0xe0, + + 0x3f, 0xb0, 0x04, 0xe0, 0x3c, 0xb0, 0x01, 0x60, + 0xf0, 0x16, 0xe0, 0x3e, 0xf0, 0x3a, 0xaa, 0x20, + + 0x9e, 0x9a, 0xd0, 0x01, 0x88, 0x84, 0x2a, 0x84, + 0x2b, 0x84, 0x2c, 0x84, 0x2d, 0xa9, 0x40, 0x60, + + 0xaa, 0xa4, 0x1b, 0xb1, 0x19, 0xc9, 0x3d, 0xf0, + 0x0b, 0xc9, 0x3e, 0xf0, 0x12, 0x20, 0x9d, 0x9a, + + 0x90, 0xe2, 0xb0, 0xe1, 0xe6, 0x1b, 0x20, 0x9d, + 0x9a, 0xf0, 0xd9, 0x90, 0xd7, 0xb0, 0xd6, 0xe6, + + 0x1b, 0x20, 0x9d, 0x9a, 0xd0, 0xce, 0xf0, 0xcd, + 0xaa, 0xa4, 0x1b, 0xb1, 0x19, 0xc9, 0x3d, 0xf0, + + 0x09, 0x20, 0x9d, 0x9a, 0xf0, 0xbf, 0xb0, 0xbc, + 0x90, 0xbb, 0xe6, 0x1b, 0x20, 0x9d, 0x9a, 0xb0, + + 0xb3, 0x90, 0xb2, 0x00, 0x13, 0x53, 0x74, 0x72, + 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x6f, 0x20, + + 0x6c, 0x6f, 0x6e, 0x67, 0x00, 0x20, 0xb2, 0xbd, + 0x20, 0x20, 0x9e, 0xa8, 0xd0, 0x6a, 0x18, 0x86, + + 0x37, 0xa0, 0x00, 0xb1, 0x04, 0x65, 0x36, 0xb0, + 0xda, 0xaa, 0x48, 0xa4, 0x36, 0xb9, 0xff, 0x05, + + 0x9d, 0xff, 0x05, 0xca, 0x88, 0xd0, 0xf6, 0x20, + 0xcb, 0xbd, 0x68, 0x85, 0x36, 0xa6, 0x37, 0x98, + + 0xf0, 0x03, 0x20, 0xd1, 0x9d, 0xe0, 0x2b, 0xf0, + 0x05, 0xe0, 0x2d, 0xf0, 0x68, 0x60, 0xa8, 0xf0, + + 0xc4, 0x30, 0x38, 0x20, 0xce, 0x9d, 0xa8, 0xf0, + 0x2f, 0x30, 0x4c, 0xa0, 0x00, 0x18, 0xb1, 0x04, + + 0x65, 0x2a, 0x85, 0x2a, 0xc8, 0xb1, 0x04, 0x65, + 0x2b, 0x85, 0x2b, 0xc8, 0xb1, 0x04, 0x65, 0x2c, + + 0x85, 0x2c, 0xc8, 0xb1, 0x04, 0x65, 0x2d, 0x85, + 0x2d, 0x18, 0xa5, 0x04, 0x69, 0x04, 0x85, 0x04, + + 0xa9, 0x40, 0x90, 0xc1, 0xe6, 0x05, 0xb0, 0xbd, + 0x4c, 0x0e, 0x8c, 0x20, 0x51, 0xbd, 0x20, 0xd1, + + 0x9d, 0xa8, 0xf0, 0xf4, 0x86, 0x27, 0x30, 0x03, + 0x20, 0xbe, 0xa2, 0x20, 0x7e, 0xbd, 0x20, 0x00, + + 0xa5, 0xa6, 0x27, 0xa9, 0xff, 0xd0, 0x9e, 0x86, + 0x27, 0x20, 0xea, 0xbd, 0x20, 0x51, 0xbd, 0x20, + + 0xbe, 0xa2, 0x4c, 0x9b, 0x9c, 0xa8, 0xf0, 0xd0, + 0x30, 0x27, 0x20, 0xce, 0x9d, 0xa8, 0xf0, 0xc8, + + 0x30, 0x38, 0x38, 0xa0, 0x00, 0xb1, 0x04, 0xe5, + 0x2a, 0x85, 0x2a, 0xc8, 0xb1, 0x04, 0xe5, 0x2b, + + 0x85, 0x2b, 0xc8, 0xb1, 0x04, 0xe5, 0x2c, 0x85, + 0x2c, 0xc8, 0xb1, 0x04, 0xe5, 0x2d, 0x4c, 0x77, + + 0x9c, 0x20, 0x51, 0xbd, 0x20, 0xd1, 0x9d, 0xa8, + 0xf0, 0x9e, 0x86, 0x27, 0x30, 0x03, 0x20, 0xbe, + + 0xa2, 0x20, 0x7e, 0xbd, 0x20, 0xfd, 0xa4, 0x4c, + 0xa1, 0x9c, 0x86, 0x27, 0x20, 0xea, 0xbd, 0x20, + + 0x51, 0xbd, 0x20, 0xbe, 0xa2, 0x20, 0x7e, 0xbd, + 0x20, 0xd0, 0xa4, 0x4c, 0xa1, 0x9c, 0x20, 0xbe, + + 0xa2, 0x20, 0xea, 0xbd, 0x20, 0x51, 0xbd, 0x20, + 0xbe, 0xa2, 0x4c, 0x2c, 0x9d, 0x20, 0xbe, 0xa2, + + 0x20, 0x51, 0xbd, 0x20, 0x20, 0x9e, 0x86, 0x27, + 0xa8, 0x20, 0xfd, 0x92, 0x20, 0x7e, 0xbd, 0x20, + + 0x56, 0xa6, 0xa9, 0xff, 0xa6, 0x27, 0x4c, 0xd4, + 0x9d, 0x4c, 0x0e, 0x8c, 0xa8, 0xf0, 0xfa, 0x30, + + 0xdf, 0xa5, 0x2d, 0xc5, 0x2c, 0xd0, 0xd6, 0xa8, + 0xf0, 0x04, 0xc9, 0xff, 0xd0, 0xcf, 0x45, 0x2b, + + 0x30, 0xcb, 0x20, 0x1d, 0x9e, 0x86, 0x27, 0xa8, + 0xf0, 0xdf, 0x30, 0xb5, 0xa5, 0x2d, 0xc5, 0x2c, + + 0xd0, 0xac, 0xa8, 0xf0, 0x04, 0xc9, 0xff, 0xd0, + 0xa5, 0x45, 0x2b, 0x30, 0xa1, 0xa5, 0x2d, 0x48, + + 0x20, 0x71, 0xad, 0xa2, 0x39, 0x20, 0x44, 0xbe, + 0x20, 0xea, 0xbd, 0x68, 0x45, 0x2d, 0x85, 0x37, + + 0x20, 0x71, 0xad, 0xa0, 0x00, 0xa2, 0x00, 0x84, + 0x3f, 0x84, 0x40, 0x46, 0x3a, 0x66, 0x39, 0x90, + + 0x15, 0x18, 0x98, 0x65, 0x2a, 0xa8, 0x8a, 0x65, + 0x2b, 0xaa, 0xa5, 0x3f, 0x65, 0x2c, 0x85, 0x3f, + + 0xa5, 0x40, 0x65, 0x2d, 0x85, 0x40, 0x06, 0x2a, + 0x26, 0x2b, 0x26, 0x2c, 0x26, 0x2d, 0xa5, 0x39, + + 0x05, 0x3a, 0xd0, 0xd7, 0x84, 0x3d, 0x86, 0x3e, + 0xa5, 0x37, 0x08, 0xa2, 0x3d, 0x20, 0x56, 0xaf, + + 0x28, 0x10, 0x03, 0x20, 0x93, 0xad, 0xa6, 0x27, + 0x4c, 0xd4, 0x9d, 0x4c, 0x3c, 0x9d, 0x20, 0x94, + + 0xbd, 0x20, 0x20, 0x9e, 0xe0, 0x2a, 0xf0, 0xf3, + 0xe0, 0x2f, 0xf0, 0x09, 0xe0, 0x83, 0xf0, 0x21, + + 0xe0, 0x81, 0xf0, 0x26, 0x60, 0xa8, 0x20, 0xfd, + 0x92, 0x20, 0x51, 0xbd, 0x20, 0x20, 0x9e, 0x86, + + 0x27, 0xa8, 0x20, 0xfd, 0x92, 0x20, 0x7e, 0xbd, + 0x20, 0xad, 0xa6, 0xa6, 0x27, 0xa9, 0xff, 0xd0, + + 0xd3, 0x20, 0xbe, 0x99, 0xa5, 0x38, 0x08, 0x4c, + 0xbb, 0x9d, 0x20, 0xbe, 0x99, 0x26, 0x39, 0x26, + + 0x3a, 0x26, 0x3b, 0x26, 0x3c, 0x24, 0x37, 0x08, + 0xa2, 0x39, 0x4c, 0xbd, 0x9d, 0x20, 0x94, 0xbd, + + 0x20, 0xec, 0xad, 0x48, 0xa4, 0x1b, 0xe6, 0x1b, + 0xb1, 0x19, 0xc9, 0x20, 0xf0, 0xf6, 0xaa, 0x68, + + 0xe0, 0x5e, 0xf0, 0x01, 0x60, 0xa8, 0x20, 0xfd, + 0x92, 0x20, 0x51, 0xbd, 0x20, 0xfa, 0x92, 0xa5, + + 0x30, 0xc9, 0x87, 0xb0, 0x43, 0x20, 0x86, 0xa4, + 0xd0, 0x0f, 0x20, 0x7e, 0xbd, 0x20, 0xb5, 0xa3, + + 0xa5, 0x4a, 0x20, 0x12, 0xab, 0xa9, 0xff, 0xd0, + 0xca, 0x20, 0x81, 0xa3, 0xa5, 0x04, 0x85, 0x4b, + + 0xa5, 0x05, 0x85, 0x4c, 0x20, 0xb5, 0xa3, 0xa5, + 0x4a, 0x20, 0x12, 0xab, 0x20, 0x7d, 0xa3, 0x20, + + 0x7e, 0xbd, 0x20, 0xb5, 0xa3, 0x20, 0x01, 0xa8, + 0x20, 0xd1, 0xaa, 0x20, 0x94, 0xaa, 0x20, 0xed, + + 0xa7, 0x20, 0x56, 0xa6, 0xa9, 0xff, 0xd0, 0x9b, + 0x20, 0x81, 0xa3, 0x20, 0x99, 0xa6, 0xd0, 0xdc, + + 0x98, 0x10, 0x03, 0x20, 0xe4, 0xa3, 0xa2, 0x00, + 0xa0, 0x00, 0xb9, 0x2a, 0x00, 0x48, 0x29, 0x0f, + + 0x95, 0x3f, 0x68, 0x4a, 0x4a, 0x4a, 0x4a, 0xe8, + 0x95, 0x3f, 0xe8, 0xc8, 0xc0, 0x04, 0xd0, 0xea, + + 0xca, 0xf0, 0x04, 0xb5, 0x3f, 0xf0, 0xf9, 0xb5, + 0x3f, 0xc9, 0x0a, 0x90, 0x02, 0x69, 0x06, 0x69, + + 0x30, 0x20, 0x66, 0xa0, 0xca, 0x10, 0xf0, 0x60, + 0x10, 0x07, 0xa9, 0x2d, 0x85, 0x2e, 0x20, 0x66, + + 0xa0, 0xa5, 0x30, 0xc9, 0x81, 0xb0, 0x4e, 0x20, + 0xf4, 0xa1, 0xc6, 0x49, 0x4c, 0xd1, 0x9e, 0xae, + + 0x02, 0x04, 0xe0, 0x03, 0x90, 0x02, 0xa2, 0x00, + 0x86, 0x37, 0xad, 0x01, 0x04, 0xf0, 0x06, 0xc9, + + 0x0a, 0xb0, 0x06, 0x90, 0x06, 0xe0, 0x02, 0xf0, + 0x02, 0xa9, 0x0a, 0x85, 0x38, 0x85, 0x4e, 0xa9, + + 0x00, 0x85, 0x36, 0x85, 0x49, 0x24, 0x15, 0x30, + 0x87, 0x98, 0x30, 0x03, 0x20, 0xbe, 0xa2, 0x20, + + 0xda, 0xa1, 0xd0, 0xb4, 0xa5, 0x37, 0xd0, 0x05, + 0xa9, 0x30, 0x4c, 0x66, 0xa0, 0x4c, 0x9c, 0x9f, + + 0x20, 0x99, 0xa6, 0xd0, 0x0f, 0xc9, 0x84, 0x90, + 0x10, 0xd0, 0x06, 0xa5, 0x31, 0xc9, 0xa0, 0x90, + + 0x08, 0x20, 0x4d, 0xa2, 0xe6, 0x49, 0x4c, 0xd1, + 0x9e, 0xa5, 0x35, 0x85, 0x27, 0x20, 0x85, 0xa3, + + 0xa5, 0x4e, 0x85, 0x38, 0xa6, 0x37, 0xe0, 0x02, + 0xd0, 0x12, 0x65, 0x49, 0x30, 0x52, 0x85, 0x38, + + 0xc9, 0x0b, 0x90, 0x08, 0xa9, 0x0a, 0x85, 0x38, + 0xa9, 0x00, 0x85, 0x37, 0x20, 0x86, 0xa6, 0xa9, + + 0xa0, 0x85, 0x31, 0xa9, 0x83, 0x85, 0x30, 0xa6, + 0x38, 0xf0, 0x06, 0x20, 0x4d, 0xa2, 0xca, 0xd0, + + 0xfa, 0x20, 0xf5, 0xa7, 0x20, 0x4e, 0xa3, 0xa5, + 0x27, 0x85, 0x42, 0x20, 0x0b, 0xa5, 0xa5, 0x30, + + 0xc9, 0x84, 0xb0, 0x0e, 0x66, 0x31, 0x66, 0x32, + 0x66, 0x33, 0x66, 0x34, 0x66, 0x35, 0xe6, 0x30, + + 0xd0, 0xec, 0xa5, 0x31, 0xc9, 0xa0, 0xb0, 0x88, + 0xa5, 0x38, 0xd0, 0x11, 0xc9, 0x01, 0xf0, 0x46, + + 0x20, 0x86, 0xa6, 0xa9, 0x00, 0x85, 0x49, 0xa5, + 0x4e, 0x85, 0x38, 0xe6, 0x38, 0xa9, 0x01, 0xc5, + + 0x37, 0xf0, 0x33, 0xa4, 0x49, 0x30, 0x0c, 0xc4, + 0x38, 0xb0, 0x2b, 0xa9, 0x00, 0x85, 0x49, 0xc8, + + 0x98, 0xd0, 0x23, 0xa5, 0x37, 0xc9, 0x02, 0xf0, + 0x06, 0xa9, 0x01, 0xc0, 0xff, 0xd0, 0x17, 0xa9, + + 0x30, 0x20, 0x66, 0xa0, 0xa9, 0x2e, 0x20, 0x66, + 0xa0, 0xa9, 0x30, 0xe6, 0x49, 0xf0, 0x05, 0x20, + + 0x66, 0xa0, 0xd0, 0xf7, 0xa9, 0x80, 0x85, 0x4e, + 0x20, 0x40, 0xa0, 0xc6, 0x4e, 0xd0, 0x05, 0xa9, + + 0x2e, 0x20, 0x66, 0xa0, 0xc6, 0x38, 0xd0, 0xf0, + 0xa4, 0x37, 0x88, 0xf0, 0x18, 0x88, 0xf0, 0x11, + + 0xa4, 0x36, 0x88, 0xb9, 0x00, 0x06, 0xc9, 0x30, + 0xf0, 0xf8, 0xc9, 0x2e, 0xf0, 0x01, 0xc8, 0x84, + + 0x36, 0xa5, 0x49, 0xf0, 0x2a, 0xa9, 0x45, 0x20, + 0x66, 0xa0, 0xa5, 0x49, 0x10, 0x0a, 0xa9, 0x2d, + + 0x20, 0x66, 0xa0, 0x38, 0xa9, 0x00, 0xe5, 0x49, + 0x20, 0x52, 0xa0, 0xa5, 0x37, 0xf0, 0x10, 0xa9, + + 0x20, 0xa4, 0x49, 0x30, 0x03, 0x20, 0x66, 0xa0, + 0xe0, 0x00, 0xd0, 0x03, 0x4c, 0x66, 0xa0, 0x60, + + 0xa5, 0x31, 0x4a, 0x4a, 0x4a, 0x4a, 0x20, 0x64, + 0xa0, 0xa5, 0x31, 0x29, 0x0f, 0x85, 0x31, 0x4c, + + 0x97, 0xa1, 0xa2, 0xff, 0x38, 0xe8, 0xe9, 0x0a, + 0xb0, 0xfb, 0x69, 0x0a, 0x48, 0x8a, 0xf0, 0x03, + + 0x20, 0x64, 0xa0, 0x68, 0x09, 0x30, 0x86, 0x3b, + 0xa6, 0x36, 0x9d, 0x00, 0x06, 0xa6, 0x3b, 0xe6, + + 0x36, 0x60, 0x18, 0x86, 0x35, 0x20, 0xda, 0xa1, + 0xa9, 0xff, 0x60, 0xa2, 0x00, 0x86, 0x31, 0x86, + + 0x32, 0x86, 0x33, 0x86, 0x34, 0x86, 0x35, 0x86, + 0x48, 0x86, 0x49, 0xc9, 0x2e, 0xf0, 0x11, 0xc9, + + 0x3a, 0xb0, 0xdf, 0xe9, 0x2f, 0x30, 0xdb, 0x85, + 0x35, 0xc8, 0xb1, 0x19, 0xc9, 0x2e, 0xd0, 0x08, + + 0xa5, 0x48, 0xd0, 0x44, 0xe6, 0x48, 0xd0, 0xf1, + 0xc9, 0x45, 0xf0, 0x35, 0xc9, 0x3a, 0xb0, 0x38, + + 0xe9, 0x2f, 0x90, 0x34, 0xa6, 0x31, 0xe0, 0x18, + 0x90, 0x08, 0xa6, 0x48, 0xd0, 0xdb, 0xe6, 0x49, + + 0xb0, 0xd7, 0xa6, 0x48, 0xf0, 0x02, 0xc6, 0x49, + 0x20, 0x97, 0xa1, 0x65, 0x35, 0x85, 0x35, 0x90, + + 0xc8, 0xe6, 0x34, 0xd0, 0xc4, 0xe6, 0x33, 0xd0, + 0xc0, 0xe6, 0x32, 0xd0, 0xbc, 0xe6, 0x31, 0xd0, + + 0xb8, 0x20, 0x40, 0xa1, 0x65, 0x49, 0x85, 0x49, + 0x84, 0x1b, 0xa5, 0x49, 0x05, 0x48, 0xf0, 0x2f, + + 0x20, 0xda, 0xa1, 0xf0, 0x26, 0xa9, 0xa8, 0x85, + 0x30, 0xa9, 0x00, 0x85, 0x2f, 0x85, 0x2e, 0x20, + + 0x03, 0xa3, 0xa5, 0x49, 0x30, 0x0b, 0xf0, 0x10, + 0x20, 0xf4, 0xa1, 0xc6, 0x49, 0xd0, 0xf9, 0xf0, + + 0x07, 0x20, 0x4d, 0xa2, 0xe6, 0x49, 0xd0, 0xf9, + 0x20, 0x5c, 0xa6, 0x38, 0xa9, 0xff, 0x60, 0xa5, + + 0x32, 0x85, 0x2d, 0x29, 0x80, 0x05, 0x31, 0xd0, + 0xcc, 0xa5, 0x35, 0x85, 0x2a, 0xa5, 0x34, 0x85, + + 0x2b, 0xa5, 0x33, 0x85, 0x2c, 0xa9, 0x40, 0x38, + 0x60, 0x20, 0x4b, 0xa1, 0x49, 0xff, 0x38, 0x60, + + 0xc8, 0xb1, 0x19, 0xc9, 0x2d, 0xf0, 0xf2, 0xc9, + 0x2b, 0xd0, 0x03, 0xc8, 0xb1, 0x19, 0xc9, 0x3a, + + 0xb0, 0x22, 0xe9, 0x2f, 0x90, 0x1e, 0x85, 0x4a, + 0xc8, 0xb1, 0x19, 0xc9, 0x3a, 0xb0, 0x11, 0xe9, + + 0x2f, 0x90, 0x0d, 0xc8, 0x85, 0x43, 0xa5, 0x4a, + 0x0a, 0x0a, 0x65, 0x4a, 0x0a, 0x65, 0x43, 0x60, + + 0xa5, 0x4a, 0x18, 0x60, 0xa9, 0x00, 0x18, 0x60, + 0xa5, 0x35, 0x65, 0x42, 0x85, 0x35, 0xa5, 0x34, + + 0x65, 0x41, 0x85, 0x34, 0xa5, 0x33, 0x65, 0x40, + 0x85, 0x33, 0xa5, 0x32, 0x65, 0x3f, 0x85, 0x32, + + 0xa5, 0x31, 0x65, 0x3e, 0x85, 0x31, 0x60, 0x48, + 0xa6, 0x34, 0xa5, 0x31, 0x48, 0xa5, 0x32, 0x48, + + 0xa5, 0x33, 0x48, 0xa5, 0x35, 0x0a, 0x26, 0x34, + 0x26, 0x33, 0x26, 0x32, 0x26, 0x31, 0x0a, 0x26, + + 0x34, 0x26, 0x33, 0x26, 0x32, 0x26, 0x31, 0x65, + 0x35, 0x85, 0x35, 0x8a, 0x65, 0x34, 0x85, 0x34, + + 0x68, 0x65, 0x33, 0x85, 0x33, 0x68, 0x65, 0x32, + 0x85, 0x32, 0x68, 0x65, 0x31, 0x06, 0x35, 0x26, + + 0x34, 0x26, 0x33, 0x26, 0x32, 0x2a, 0x85, 0x31, + 0x68, 0x60, 0xa5, 0x31, 0x05, 0x32, 0x05, 0x33, + + 0x05, 0x34, 0x05, 0x35, 0xf0, 0x07, 0xa5, 0x2e, + 0xd0, 0x09, 0xa9, 0x01, 0x60, 0x85, 0x2e, 0x85, + + 0x30, 0x85, 0x2f, 0x60, 0x18, 0xa5, 0x30, 0x69, + 0x03, 0x85, 0x30, 0x90, 0x02, 0xe6, 0x2f, 0x20, + + 0x1e, 0xa2, 0x20, 0x42, 0xa2, 0x20, 0x42, 0xa2, + 0x20, 0x78, 0xa1, 0x90, 0x10, 0x66, 0x31, 0x66, + + 0x32, 0x66, 0x33, 0x66, 0x34, 0x66, 0x35, 0xe6, + 0x30, 0xd0, 0x02, 0xe6, 0x2f, 0x60, 0xa5, 0x2e, + + 0x85, 0x3b, 0xa5, 0x2f, 0x85, 0x3c, 0xa5, 0x30, + 0x85, 0x3d, 0xa5, 0x31, 0x85, 0x3e, 0xa5, 0x32, + + 0x85, 0x3f, 0xa5, 0x33, 0x85, 0x40, 0xa5, 0x34, + 0x85, 0x41, 0xa5, 0x35, 0x85, 0x42, 0x60, 0x20, + + 0x1e, 0xa2, 0x46, 0x3e, 0x66, 0x3f, 0x66, 0x40, + 0x66, 0x41, 0x66, 0x42, 0x60, 0x38, 0xa5, 0x30, + + 0xe9, 0x04, 0x85, 0x30, 0xb0, 0x02, 0xc6, 0x2f, + 0x20, 0x3f, 0xa2, 0x20, 0x08, 0xa2, 0x20, 0x3f, + + 0xa2, 0x20, 0x42, 0xa2, 0x20, 0x42, 0xa2, 0x20, + 0x42, 0xa2, 0x20, 0x08, 0xa2, 0xa9, 0x00, 0x85, + + 0x3e, 0xa5, 0x31, 0x85, 0x3f, 0xa5, 0x32, 0x85, + 0x40, 0xa5, 0x33, 0x85, 0x41, 0xa5, 0x34, 0x85, + + 0x42, 0xa5, 0x35, 0x2a, 0x20, 0x08, 0xa2, 0xa9, + 0x00, 0x85, 0x3e, 0x85, 0x3f, 0xa5, 0x31, 0x85, + + 0x40, 0xa5, 0x32, 0x85, 0x41, 0xa5, 0x33, 0x85, + 0x42, 0xa5, 0x34, 0x2a, 0x20, 0x08, 0xa2, 0xa5, + + 0x32, 0x2a, 0xa5, 0x31, 0x65, 0x35, 0x85, 0x35, + 0x90, 0x13, 0xe6, 0x34, 0xd0, 0x0f, 0xe6, 0x33, + + 0xd0, 0x0b, 0xe6, 0x32, 0xd0, 0x07, 0xe6, 0x31, + 0xd0, 0x03, 0x4c, 0x0b, 0xa2, 0x60, 0xa2, 0x00, + + 0x86, 0x35, 0x86, 0x2f, 0xa5, 0x2d, 0x10, 0x05, + 0x20, 0x93, 0xad, 0xa2, 0xff, 0x86, 0x2e, 0xa5, + + 0x2a, 0x85, 0x34, 0xa5, 0x2b, 0x85, 0x33, 0xa5, + 0x2c, 0x85, 0x32, 0xa5, 0x2d, 0x85, 0x31, 0xa9, + + 0xa0, 0x85, 0x30, 0x4c, 0x03, 0xa3, 0x85, 0x2e, + 0x85, 0x30, 0x85, 0x2f, 0x60, 0x48, 0x20, 0x86, + + 0xa6, 0x68, 0xf0, 0xf8, 0x10, 0x07, 0x85, 0x2e, + 0xa9, 0x00, 0x38, 0xe5, 0x2e, 0x85, 0x31, 0xa9, + + 0x88, 0x85, 0x30, 0xa5, 0x31, 0x30, 0xe5, 0x05, + 0x32, 0x05, 0x33, 0x05, 0x34, 0x05, 0x35, 0xf0, + + 0xd5, 0xa5, 0x30, 0xa4, 0x31, 0x30, 0xd5, 0xd0, + 0x21, 0xa6, 0x32, 0x86, 0x31, 0xa6, 0x33, 0x86, + + 0x32, 0xa6, 0x34, 0x86, 0x33, 0xa6, 0x35, 0x86, + 0x34, 0x84, 0x35, 0x38, 0xe9, 0x08, 0x85, 0x30, + + 0xb0, 0xe1, 0xc6, 0x2f, 0x90, 0xdd, 0xa4, 0x31, + 0x30, 0xb2, 0x06, 0x35, 0x26, 0x34, 0x26, 0x33, + + 0x26, 0x32, 0x26, 0x31, 0xe9, 0x00, 0x85, 0x30, + 0xb0, 0xec, 0xc6, 0x2f, 0x90, 0xe8, 0xa0, 0x04, + + 0xb1, 0x4b, 0x85, 0x41, 0x88, 0xb1, 0x4b, 0x85, + 0x40, 0x88, 0xb1, 0x4b, 0x85, 0x3f, 0x88, 0xb1, + + 0x4b, 0x85, 0x3b, 0x88, 0x84, 0x42, 0x84, 0x3c, + 0xb1, 0x4b, 0x85, 0x3d, 0x05, 0x3b, 0x05, 0x3f, + + 0x05, 0x40, 0x05, 0x41, 0xf0, 0x04, 0xa5, 0x3b, + 0x09, 0x80, 0x85, 0x3e, 0x60, 0xa9, 0x71, 0xd0, + + 0x06, 0xa9, 0x76, 0xd0, 0x02, 0xa9, 0x6c, 0x85, + 0x4b, 0xa9, 0x04, 0x85, 0x4c, 0xa0, 0x00, 0xa5, + + 0x30, 0x91, 0x4b, 0xc8, 0xa5, 0x2e, 0x29, 0x80, + 0x85, 0x2e, 0xa5, 0x31, 0x29, 0x7f, 0x05, 0x2e, + + 0x91, 0x4b, 0xa5, 0x32, 0xc8, 0x91, 0x4b, 0xa5, + 0x33, 0xc8, 0x91, 0x4b, 0xa5, 0x34, 0xc8, 0x91, + + 0x4b, 0x60, 0x20, 0xf5, 0xa7, 0xa0, 0x04, 0xb1, + 0x4b, 0x85, 0x34, 0x88, 0xb1, 0x4b, 0x85, 0x33, + + 0x88, 0xb1, 0x4b, 0x85, 0x32, 0x88, 0xb1, 0x4b, + 0x85, 0x2e, 0x88, 0xb1, 0x4b, 0x85, 0x30, 0x84, + + 0x35, 0x84, 0x2f, 0x05, 0x2e, 0x05, 0x32, 0x05, + 0x33, 0x05, 0x34, 0xf0, 0x04, 0xa5, 0x2e, 0x09, + + 0x80, 0x85, 0x31, 0x60, 0x20, 0xfe, 0xa3, 0xa5, + 0x31, 0x85, 0x2d, 0xa5, 0x32, 0x85, 0x2c, 0xa5, + + 0x33, 0x85, 0x2b, 0xa5, 0x34, 0x85, 0x2a, 0x60, + 0x20, 0x1e, 0xa2, 0x4c, 0x86, 0xa6, 0xa5, 0x30, + + 0x10, 0xf6, 0x20, 0x53, 0xa4, 0x20, 0xda, 0xa1, + 0xd0, 0x32, 0xf0, 0x5c, 0xa5, 0x30, 0xc9, 0xa0, + + 0xb0, 0x54, 0xc9, 0x99, 0xb0, 0x26, 0x69, 0x08, + 0x85, 0x30, 0xa5, 0x40, 0x85, 0x41, 0xa5, 0x3f, + + 0x85, 0x40, 0xa5, 0x3e, 0x85, 0x3f, 0xa5, 0x34, + 0x85, 0x3e, 0xa5, 0x33, 0x85, 0x34, 0xa5, 0x32, + + 0x85, 0x33, 0xa5, 0x31, 0x85, 0x32, 0xa9, 0x00, + 0x85, 0x31, 0xf0, 0xd0, 0x46, 0x31, 0x66, 0x32, + + 0x66, 0x33, 0x66, 0x34, 0x66, 0x3e, 0x66, 0x3f, + 0x66, 0x40, 0x66, 0x41, 0xe6, 0x30, 0xd0, 0xbc, + + 0x4c, 0x6c, 0xa6, 0xa9, 0x00, 0x85, 0x3b, 0x85, + 0x3c, 0x85, 0x3d, 0x85, 0x3e, 0x85, 0x3f, 0x85, + + 0x40, 0x85, 0x41, 0x85, 0x42, 0x60, 0xd0, 0xe8, + 0xa5, 0x2e, 0x10, 0x19, 0x38, 0xa9, 0x00, 0xe5, + + 0x34, 0x85, 0x34, 0xa9, 0x00, 0xe5, 0x33, 0x85, + 0x33, 0xa9, 0x00, 0xe5, 0x32, 0x85, 0x32, 0xa9, + + 0x00, 0xe5, 0x31, 0x85, 0x31, 0x60, 0xa5, 0x30, + 0x30, 0x07, 0xa9, 0x00, 0x85, 0x4a, 0x4c, 0xda, + + 0xa1, 0x20, 0xfe, 0xa3, 0xa5, 0x34, 0x85, 0x4a, + 0x20, 0xe8, 0xa4, 0xa9, 0x80, 0x85, 0x30, 0xa6, + + 0x31, 0x10, 0x10, 0x45, 0x2e, 0x85, 0x2e, 0x10, + 0x05, 0xe6, 0x4a, 0x4c, 0xb0, 0xa4, 0xc6, 0x4a, + + 0x20, 0x6c, 0xa4, 0x4c, 0x03, 0xa3, 0xe6, 0x34, + 0xd0, 0x0c, 0xe6, 0x33, 0xd0, 0x08, 0xe6, 0x32, + + 0xd0, 0x04, 0xe6, 0x31, 0xf0, 0x8a, 0x60, 0x20, + 0x6c, 0xa4, 0x20, 0xb6, 0xa4, 0x4c, 0x6c, 0xa4, + + 0x20, 0xfd, 0xa4, 0x4c, 0x7e, 0xad, 0x20, 0x4e, + 0xa3, 0x20, 0x8d, 0xa3, 0xa5, 0x3b, 0x85, 0x2e, + + 0xa5, 0x3c, 0x85, 0x2f, 0xa5, 0x3d, 0x85, 0x30, + 0xa5, 0x3e, 0x85, 0x31, 0xa5, 0x3f, 0x85, 0x32, + + 0xa5, 0x40, 0x85, 0x33, 0xa5, 0x41, 0x85, 0x34, + 0xa5, 0x42, 0x85, 0x35, 0x60, 0x20, 0x7e, 0xad, + + 0x20, 0x4e, 0xa3, 0xf0, 0xf7, 0x20, 0x0b, 0xa5, + 0x4c, 0x5c, 0xa6, 0x20, 0xda, 0xa1, 0xf0, 0xcc, + + 0xa0, 0x00, 0x38, 0xa5, 0x30, 0xe5, 0x3d, 0xf0, + 0x77, 0x90, 0x37, 0xc9, 0x25, 0xb0, 0xdd, 0x48, + + 0x29, 0x38, 0xf0, 0x19, 0x4a, 0x4a, 0x4a, 0xaa, + 0xa5, 0x41, 0x85, 0x42, 0xa5, 0x40, 0x85, 0x41, + + 0xa5, 0x3f, 0x85, 0x40, 0xa5, 0x3e, 0x85, 0x3f, + 0x84, 0x3e, 0xca, 0xd0, 0xeb, 0x68, 0x29, 0x07, + + 0xf0, 0x4e, 0xaa, 0x46, 0x3e, 0x66, 0x3f, 0x66, + 0x40, 0x66, 0x41, 0x66, 0x42, 0xca, 0xd0, 0xf3, + + 0xf0, 0x3e, 0x38, 0xa5, 0x3d, 0xe5, 0x30, 0xc9, + 0x25, 0xb0, 0x81, 0x48, 0x29, 0x38, 0xf0, 0x19, + + 0x4a, 0x4a, 0x4a, 0xaa, 0xa5, 0x34, 0x85, 0x35, + 0xa5, 0x33, 0x85, 0x34, 0xa5, 0x32, 0x85, 0x33, + + 0xa5, 0x31, 0x85, 0x32, 0x84, 0x31, 0xca, 0xd0, + 0xeb, 0x68, 0x29, 0x07, 0xf0, 0x0e, 0xaa, 0x46, + + 0x31, 0x66, 0x32, 0x66, 0x33, 0x66, 0x34, 0x66, + 0x35, 0xca, 0xd0, 0xf3, 0xa5, 0x3d, 0x85, 0x30, + + 0xa5, 0x2e, 0x45, 0x3b, 0x10, 0x49, 0xa5, 0x31, + 0xc5, 0x3e, 0xd0, 0x1b, 0xa5, 0x32, 0xc5, 0x3f, + + 0xd0, 0x15, 0xa5, 0x33, 0xc5, 0x40, 0xd0, 0x0f, + 0xa5, 0x34, 0xc5, 0x41, 0xd0, 0x09, 0xa5, 0x35, + + 0xc5, 0x42, 0xd0, 0x03, 0x4c, 0x86, 0xa6, 0xb0, + 0x2a, 0x38, 0xa5, 0x42, 0xe5, 0x35, 0x85, 0x35, + + 0xa5, 0x41, 0xe5, 0x34, 0x85, 0x34, 0xa5, 0x40, + 0xe5, 0x33, 0x85, 0x33, 0xa5, 0x3f, 0xe5, 0x32, + + 0x85, 0x32, 0xa5, 0x3e, 0xe5, 0x31, 0x85, 0x31, + 0xa5, 0x3b, 0x85, 0x2e, 0x4c, 0x03, 0xa3, 0x18, + + 0x4c, 0x08, 0xa2, 0x38, 0xa5, 0x35, 0xe5, 0x42, + 0x85, 0x35, 0xa5, 0x34, 0xe5, 0x41, 0x85, 0x34, + + 0xa5, 0x33, 0xe5, 0x40, 0x85, 0x33, 0xa5, 0x32, + 0xe5, 0x3f, 0x85, 0x32, 0xa5, 0x31, 0xe5, 0x3e, + + 0x85, 0x31, 0x4c, 0x03, 0xa3, 0x60, 0x20, 0xda, + 0xa1, 0xf0, 0xfa, 0x20, 0x4e, 0xa3, 0xd0, 0x03, + + 0x4c, 0x86, 0xa6, 0x18, 0xa5, 0x30, 0x65, 0x3d, + 0x90, 0x03, 0xe6, 0x2f, 0x18, 0xe9, 0x7f, 0x85, + + 0x30, 0xb0, 0x02, 0xc6, 0x2f, 0xa2, 0x05, 0xa0, + 0x00, 0xb5, 0x30, 0x95, 0x42, 0x94, 0x30, 0xca, + + 0xd0, 0xf7, 0xa5, 0x2e, 0x45, 0x3b, 0x85, 0x2e, + 0xa0, 0x20, 0x46, 0x3e, 0x66, 0x3f, 0x66, 0x40, + + 0x66, 0x41, 0x66, 0x42, 0x06, 0x46, 0x26, 0x45, + 0x26, 0x44, 0x26, 0x43, 0x90, 0x04, 0x18, 0x20, + + 0x78, 0xa1, 0x88, 0xd0, 0xe5, 0x60, 0x20, 0x06, + 0xa6, 0x20, 0x03, 0xa3, 0xa5, 0x35, 0xc9, 0x80, + + 0x90, 0x1a, 0xf0, 0x12, 0xa9, 0xff, 0x20, 0xa4, + 0xa2, 0x4c, 0x7c, 0xa6, 0x00, 0x14, 0x54, 0x6f, + + 0x6f, 0x20, 0x62, 0x69, 0x67, 0x00, 0xa5, 0x34, + 0x09, 0x01, 0x85, 0x34, 0xa9, 0x00, 0x85, 0x35, + + 0xa5, 0x2f, 0xf0, 0x14, 0x10, 0xe6, 0xa9, 0x00, + 0x85, 0x2e, 0x85, 0x2f, 0x85, 0x30, 0x85, 0x31, + + 0x85, 0x32, 0x85, 0x33, 0x85, 0x34, 0x85, 0x35, + 0x60, 0x20, 0x86, 0xa6, 0xa0, 0x80, 0x84, 0x31, + + 0xc8, 0x84, 0x30, 0x98, 0x60, 0x20, 0x85, 0xa3, + 0x20, 0x99, 0xa6, 0xd0, 0x3a, 0x20, 0xda, 0xa1, + + 0xf0, 0x09, 0x20, 0x1e, 0xa2, 0x20, 0xb5, 0xa3, + 0xd0, 0x37, 0x60, 0x4c, 0xa7, 0x99, 0x20, 0xfa, + + 0x92, 0x20, 0xd3, 0xa9, 0xa5, 0x4a, 0x48, 0x20, + 0xe9, 0xa7, 0x20, 0x8d, 0xa3, 0xe6, 0x4a, 0x20, + + 0x9e, 0xa9, 0x20, 0xe9, 0xa7, 0x20, 0xd6, 0xa4, + 0x68, 0x85, 0x4a, 0x20, 0x9e, 0xa9, 0x20, 0xe9, + + 0xa7, 0x20, 0xe7, 0xa6, 0xa9, 0xff, 0x60, 0x20, + 0xda, 0xa1, 0xf0, 0xac, 0x20, 0x4e, 0xa3, 0xf0, + + 0xca, 0xa5, 0x2e, 0x45, 0x3b, 0x85, 0x2e, 0x38, + 0xa5, 0x30, 0xe5, 0x3d, 0xb0, 0x03, 0xc6, 0x2f, + + 0x38, 0x69, 0x80, 0x85, 0x30, 0x90, 0x03, 0xe6, + 0x2f, 0x18, 0xa2, 0x20, 0xb0, 0x18, 0xa5, 0x31, + + 0xc5, 0x3e, 0xd0, 0x10, 0xa5, 0x32, 0xc5, 0x3f, + 0xd0, 0x0a, 0xa5, 0x33, 0xc5, 0x40, 0xd0, 0x04, + + 0xa5, 0x34, 0xc5, 0x41, 0x90, 0x19, 0xa5, 0x34, + 0xe5, 0x41, 0x85, 0x34, 0xa5, 0x33, 0xe5, 0x40, + + 0x85, 0x33, 0xa5, 0x32, 0xe5, 0x3f, 0x85, 0x32, + 0xa5, 0x31, 0xe5, 0x3e, 0x85, 0x31, 0x38, 0x26, + + 0x46, 0x26, 0x45, 0x26, 0x44, 0x26, 0x43, 0x06, + 0x34, 0x26, 0x33, 0x26, 0x32, 0x26, 0x31, 0xca, + + 0xd0, 0xba, 0xa2, 0x07, 0xb0, 0x18, 0xa5, 0x31, + 0xc5, 0x3e, 0xd0, 0x10, 0xa5, 0x32, 0xc5, 0x3f, + + 0xd0, 0x0a, 0xa5, 0x33, 0xc5, 0x40, 0xd0, 0x04, + 0xa5, 0x34, 0xc5, 0x41, 0x90, 0x19, 0xa5, 0x34, + + 0xe5, 0x41, 0x85, 0x34, 0xa5, 0x33, 0xe5, 0x40, + 0x85, 0x33, 0xa5, 0x32, 0xe5, 0x3f, 0x85, 0x32, + + 0xa5, 0x31, 0xe5, 0x3e, 0x85, 0x31, 0x38, 0x26, + 0x35, 0x06, 0x34, 0x26, 0x33, 0x26, 0x32, 0x26, + + 0x31, 0xca, 0xd0, 0xc0, 0x06, 0x35, 0xa5, 0x46, + 0x85, 0x34, 0xa5, 0x45, 0x85, 0x33, 0xa5, 0x44, + + 0x85, 0x32, 0xa5, 0x43, 0x85, 0x31, 0x4c, 0x59, + 0xa6, 0x00, 0x15, 0x2d, 0x76, 0x65, 0x20, 0x72, + + 0x6f, 0x6f, 0x74, 0x00, 0x20, 0xfa, 0x92, 0x20, + 0xda, 0xa1, 0xf0, 0x2a, 0x30, 0xeb, 0x20, 0x85, + + 0xa3, 0xa5, 0x30, 0x4a, 0x69, 0x40, 0x85, 0x30, + 0xa9, 0x05, 0x85, 0x4a, 0x20, 0xed, 0xa7, 0x20, + + 0x8d, 0xa3, 0xa9, 0x6c, 0x85, 0x4b, 0x20, 0xad, + 0xa6, 0xa9, 0x71, 0x85, 0x4b, 0x20, 0x00, 0xa5, + + 0xc6, 0x30, 0xc6, 0x4a, 0xd0, 0xe9, 0xa9, 0xff, + 0x60, 0xa9, 0x7b, 0xd0, 0x0a, 0xa9, 0x71, 0xd0, + + 0x06, 0xa9, 0x76, 0xd0, 0x02, 0xa9, 0x6c, 0x85, + 0x4b, 0xa9, 0x04, 0x85, 0x4c, 0x60, 0x20, 0xfa, + + 0x92, 0x20, 0xda, 0xa1, 0xf0, 0x02, 0x10, 0x0c, + 0x00, 0x16, 0x4c, 0x6f, 0x67, 0x20, 0x72, 0x61, + + 0x6e, 0x67, 0x65, 0x00, 0x20, 0x53, 0xa4, 0xa0, + 0x80, 0x84, 0x3b, 0x84, 0x3e, 0xc8, 0x84, 0x3d, + + 0xa6, 0x30, 0xf0, 0x06, 0xa5, 0x31, 0xc9, 0xb5, + 0x90, 0x02, 0xe8, 0x88, 0x8a, 0x48, 0x84, 0x30, + + 0x20, 0x05, 0xa5, 0xa9, 0x7b, 0x20, 0x87, 0xa3, + 0xa9, 0x73, 0xa0, 0xa8, 0x20, 0x97, 0xa8, 0x20, + + 0xe9, 0xa7, 0x20, 0x56, 0xa6, 0x20, 0x56, 0xa6, + 0x20, 0x00, 0xa5, 0x20, 0x85, 0xa3, 0x68, 0x38, + + 0xe9, 0x81, 0x20, 0xed, 0xa2, 0xa9, 0x6e, 0x85, + 0x4b, 0xa9, 0xa8, 0x85, 0x4c, 0x20, 0x56, 0xa6, + + 0x20, 0xf5, 0xa7, 0x20, 0x00, 0xa5, 0xa9, 0xff, + 0x60, 0x7f, 0x5e, 0x5b, 0xd8, 0xaa, 0x80, 0x31, + + 0x72, 0x17, 0xf8, 0x06, 0x7a, 0x12, 0x38, 0xa5, + 0x0b, 0x88, 0x79, 0x0e, 0x9f, 0xf3, 0x7c, 0x2a, + + 0xac, 0x3f, 0xb5, 0x86, 0x34, 0x01, 0xa2, 0x7a, + 0x7f, 0x63, 0x8e, 0x37, 0xec, 0x82, 0x3f, 0xff, + + 0xff, 0xc1, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x85, + 0x4d, 0x84, 0x4e, 0x20, 0x85, 0xa3, 0xa0, 0x00, + + 0xb1, 0x4d, 0x85, 0x48, 0xe6, 0x4d, 0xd0, 0x02, + 0xe6, 0x4e, 0xa5, 0x4d, 0x85, 0x4b, 0xa5, 0x4e, + + 0x85, 0x4c, 0x20, 0xb5, 0xa3, 0x20, 0xf5, 0xa7, + 0x20, 0xad, 0xa6, 0x18, 0xa5, 0x4d, 0x69, 0x05, + + 0x85, 0x4d, 0x85, 0x4b, 0xa5, 0x4e, 0x69, 0x00, + 0x85, 0x4e, 0x85, 0x4c, 0x20, 0x00, 0xa5, 0xc6, + + 0x48, 0xd0, 0xe2, 0x60, 0x20, 0xda, 0xa8, 0x4c, + 0x27, 0xa9, 0x20, 0xfa, 0x92, 0x20, 0xda, 0xa1, + + 0x10, 0x08, 0x46, 0x2e, 0x20, 0xea, 0xa8, 0x4c, + 0x16, 0xa9, 0x20, 0x81, 0xa3, 0x20, 0xb1, 0xa9, + + 0x20, 0xda, 0xa1, 0xf0, 0x09, 0x20, 0xf1, 0xa7, + 0x20, 0xad, 0xa6, 0x4c, 0x0a, 0xa9, 0x20, 0x55, + + 0xaa, 0x20, 0xb5, 0xa3, 0xa9, 0xff, 0x60, 0x20, + 0xfa, 0x92, 0x20, 0xda, 0xa1, 0xf0, 0xf5, 0x10, + + 0x0a, 0x46, 0x2e, 0x20, 0x1b, 0xa9, 0xa9, 0x80, + 0x85, 0x2e, 0x60, 0xa5, 0x30, 0xc9, 0x81, 0x90, + + 0x15, 0x20, 0xa5, 0xa6, 0x20, 0x36, 0xa9, 0x20, + 0x48, 0xaa, 0x20, 0x00, 0xa5, 0x20, 0x4c, 0xaa, + + 0x20, 0x00, 0xa5, 0x4c, 0x7e, 0xad, 0xa5, 0x30, + 0xc9, 0x73, 0x90, 0xc8, 0x20, 0x81, 0xa3, 0x20, + + 0x53, 0xa4, 0xa9, 0x80, 0x85, 0x3d, 0x85, 0x3e, + 0x85, 0x3b, 0x20, 0x05, 0xa5, 0xa9, 0x5a, 0xa0, + + 0xa9, 0x20, 0x97, 0xa8, 0x20, 0xd1, 0xaa, 0xa9, + 0xff, 0x60, 0x09, 0x85, 0xa3, 0x59, 0xe8, 0x67, + + 0x80, 0x1c, 0x9d, 0x07, 0x36, 0x80, 0x57, 0xbb, + 0x78, 0xdf, 0x80, 0xca, 0x9a, 0x0e, 0x83, 0x84, + + 0x8c, 0xbb, 0xca, 0x6e, 0x81, 0x95, 0x96, 0x06, + 0xde, 0x81, 0x0a, 0xc7, 0x6c, 0x52, 0x7f, 0x7d, + + 0xad, 0x90, 0xa1, 0x82, 0xfb, 0x62, 0x57, 0x2f, + 0x80, 0x6d, 0x63, 0x38, 0x2c, 0x20, 0xfa, 0x92, + + 0x20, 0xd3, 0xa9, 0xe6, 0x4a, 0x4c, 0x9e, 0xa9, + 0x20, 0xfa, 0x92, 0x20, 0xd3, 0xa9, 0xa5, 0x4a, + + 0x29, 0x02, 0xf0, 0x06, 0x20, 0xaa, 0xa9, 0x4c, + 0x7e, 0xad, 0x46, 0x4a, 0x90, 0x15, 0x20, 0xc3, + + 0xa9, 0x20, 0x85, 0xa3, 0x20, 0x56, 0xa6, 0x20, + 0x8d, 0xa3, 0x20, 0x99, 0xa6, 0x20, 0xd0, 0xa4, + + 0x4c, 0xb7, 0xa7, 0x20, 0x81, 0xa3, 0x20, 0x56, + 0xa6, 0xa9, 0x72, 0xa0, 0xaa, 0x20, 0x97, 0xa8, + + 0x4c, 0xd1, 0xaa, 0xa5, 0x30, 0xc9, 0x98, 0xb0, + 0x5f, 0x20, 0x85, 0xa3, 0x20, 0x55, 0xaa, 0x20, + + 0x4e, 0xa3, 0xa5, 0x2e, 0x85, 0x3b, 0xc6, 0x3d, + 0x20, 0x05, 0xa5, 0x20, 0xe7, 0xa6, 0x20, 0xfe, + + 0xa3, 0xa5, 0x34, 0x85, 0x4a, 0x05, 0x33, 0x05, + 0x32, 0x05, 0x31, 0xf0, 0x38, 0xa9, 0xa0, 0x85, + + 0x30, 0xa0, 0x00, 0x84, 0x35, 0xa5, 0x31, 0x85, + 0x2e, 0x10, 0x03, 0x20, 0x6c, 0xa4, 0x20, 0x03, + + 0xa3, 0x20, 0x7d, 0xa3, 0x20, 0x48, 0xaa, 0x20, + 0x56, 0xa6, 0x20, 0xf5, 0xa7, 0x20, 0x00, 0xa5, + + 0x20, 0x8d, 0xa3, 0x20, 0xed, 0xa7, 0x20, 0xb5, + 0xa3, 0x20, 0x4c, 0xaa, 0x20, 0x56, 0xa6, 0x20, + + 0xf5, 0xa7, 0x4c, 0x00, 0xa5, 0x4c, 0xb2, 0xa3, + 0x00, 0x17, 0x41, 0x63, 0x63, 0x75, 0x72, 0x61, + + 0x63, 0x79, 0x20, 0x6c, 0x6f, 0x73, 0x74, 0x00, + 0xa9, 0x59, 0xd0, 0x02, 0xa9, 0x5e, 0x85, 0x4b, + + 0xa9, 0xaa, 0x85, 0x4c, 0x60, 0xa9, 0x63, 0xd0, + 0xf5, 0x81, 0xc9, 0x10, 0x00, 0x00, 0x6f, 0x15, + + 0x77, 0x7a, 0x61, 0x81, 0x49, 0x0f, 0xda, 0xa2, + 0x7b, 0x0e, 0xfa, 0x35, 0x12, 0x86, 0x65, 0x2e, + + 0xe0, 0xd3, 0x05, 0x84, 0x8a, 0xea, 0x0c, 0x1b, + 0x84, 0x1a, 0xbe, 0xbb, 0x2b, 0x84, 0x37, 0x45, + + 0x55, 0xab, 0x82, 0xd5, 0x55, 0x57, 0x7c, 0x83, + 0xc0, 0x00, 0x00, 0x05, 0x81, 0x00, 0x00, 0x00, + + 0x00, 0x20, 0xfa, 0x92, 0xa5, 0x30, 0xc9, 0x87, + 0x90, 0x1e, 0xd0, 0x06, 0xa4, 0x31, 0xc0, 0xb3, + + 0x90, 0x16, 0xa5, 0x2e, 0x10, 0x06, 0x20, 0x86, + 0xa6, 0xa9, 0xff, 0x60, 0x00, 0x18, 0x45, 0x78, + + 0x70, 0x20, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x00, + 0x20, 0x86, 0xa4, 0x20, 0xda, 0xaa, 0x20, 0x81, + + 0xa3, 0xa9, 0xe4, 0x85, 0x4b, 0xa9, 0xaa, 0x85, + 0x4c, 0x20, 0xb5, 0xa3, 0xa5, 0x4a, 0x20, 0x12, + + 0xab, 0x20, 0xf1, 0xa7, 0x20, 0x56, 0xa6, 0xa9, + 0xff, 0x60, 0xa9, 0xe9, 0xa0, 0xaa, 0x20, 0x97, + + 0xa8, 0xa9, 0xff, 0x60, 0x82, 0x2d, 0xf8, 0x54, + 0x58, 0x07, 0x83, 0xe0, 0x20, 0x86, 0x5b, 0x82, + + 0x80, 0x53, 0x93, 0xb8, 0x83, 0x20, 0x00, 0x06, + 0xa1, 0x82, 0x00, 0x00, 0x21, 0x63, 0x82, 0xc0, + + 0x00, 0x00, 0x02, 0x82, 0x80, 0x00, 0x00, 0x0c, + 0x81, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, + + 0x00, 0x00, 0xaa, 0x10, 0x09, 0xca, 0x8a, 0x49, + 0xff, 0x48, 0x20, 0xa5, 0xa6, 0x68, 0x48, 0x20, + + 0x85, 0xa3, 0x20, 0x99, 0xa6, 0x68, 0xf0, 0x0a, + 0x38, 0xe9, 0x01, 0x48, 0x20, 0x56, 0xa6, 0x4c, + + 0x25, 0xab, 0x60, 0x20, 0xe3, 0x92, 0xa6, 0x2a, + 0xa9, 0x80, 0x20, 0xf4, 0xff, 0x8a, 0x4c, 0xea, + + 0xae, 0x20, 0xdd, 0x92, 0x20, 0x94, 0xbd, 0x20, + 0xae, 0x8a, 0x20, 0x56, 0xae, 0x20, 0xf0, 0x92, + + 0xa5, 0x2a, 0x48, 0xa5, 0x2b, 0x48, 0x20, 0xea, + 0xbd, 0x68, 0x85, 0x2d, 0x68, 0x85, 0x2c, 0xa2, + + 0x2a, 0xa9, 0x09, 0x20, 0xf1, 0xff, 0xa5, 0x2e, + 0x30, 0x33, 0x4c, 0xd8, 0xae, 0xa9, 0x86, 0x20, + + 0xf4, 0xff, 0x8a, 0x4c, 0xd8, 0xae, 0xa9, 0x86, + 0x20, 0xf4, 0xff, 0x98, 0x4c, 0xd8, 0xae, 0x20, + + 0xda, 0xa1, 0xf0, 0x1e, 0x10, 0x1a, 0x30, 0x15, + 0x20, 0xec, 0xad, 0xf0, 0x59, 0x30, 0xf0, 0xa5, + + 0x2d, 0x05, 0x2c, 0x05, 0x2b, 0x05, 0x2a, 0xf0, + 0x0c, 0xa5, 0x2d, 0x10, 0x03, 0x4c, 0xc4, 0xac, + + 0xa9, 0x01, 0x4c, 0xd8, 0xae, 0xa9, 0x40, 0x60, + 0x20, 0xfe, 0xa7, 0xa0, 0x69, 0xa9, 0xa8, 0xd0, + + 0x07, 0x20, 0xfa, 0x92, 0xa0, 0x68, 0xa9, 0xaa, + 0x84, 0x4b, 0x85, 0x4c, 0x20, 0x56, 0xa6, 0xa9, + + 0xff, 0x60, 0x20, 0xfa, 0x92, 0xa0, 0x6d, 0xa9, + 0xaa, 0xd0, 0xed, 0x20, 0xfe, 0xa8, 0xe6, 0x30, + + 0xa8, 0x60, 0x20, 0xe3, 0x92, 0x20, 0x1e, 0x8f, + 0x85, 0x2a, 0x86, 0x2b, 0x84, 0x2c, 0x08, 0x68, + + 0x85, 0x2d, 0xd8, 0xa9, 0x40, 0x60, 0x4c, 0x0e, + 0x8c, 0x20, 0xec, 0xad, 0xd0, 0xf8, 0xe6, 0x36, + + 0xa4, 0x36, 0xa9, 0x0d, 0x99, 0xff, 0x05, 0x20, + 0xb2, 0xbd, 0xa5, 0x19, 0x48, 0xa5, 0x1a, 0x48, + + 0xa5, 0x1b, 0x48, 0xa4, 0x04, 0xa6, 0x05, 0xc8, + 0x84, 0x19, 0x84, 0x37, 0xd0, 0x01, 0xe8, 0x86, + + 0x1a, 0x86, 0x38, 0xa0, 0xff, 0x84, 0x3b, 0xc8, + 0x84, 0x1b, 0x20, 0x55, 0x89, 0x20, 0x29, 0x9b, + + 0x20, 0xdc, 0xbd, 0x68, 0x85, 0x1b, 0x68, 0x85, + 0x1a, 0x68, 0x85, 0x19, 0xa5, 0x27, 0x60, 0x20, + + 0xec, 0xad, 0xd0, 0x67, 0xa4, 0x36, 0xa9, 0x00, + 0x99, 0x00, 0x06, 0xa5, 0x19, 0x48, 0xa5, 0x1a, + + 0x48, 0xa5, 0x1b, 0x48, 0xa9, 0x00, 0x85, 0x1b, + 0xa9, 0x00, 0x85, 0x19, 0xa9, 0x06, 0x85, 0x1a, + + 0x20, 0x8c, 0x8a, 0xc9, 0x2d, 0xf0, 0x0f, 0xc9, + 0x2b, 0xd0, 0x03, 0x20, 0x8c, 0x8a, 0xc6, 0x1b, + + 0x20, 0x7b, 0xa0, 0x4c, 0x73, 0xac, 0x20, 0x8c, + 0x8a, 0xc6, 0x1b, 0x20, 0x7b, 0xa0, 0x90, 0x03, + + 0x20, 0x8f, 0xad, 0x85, 0x27, 0x4c, 0x23, 0xac, + 0x20, 0xec, 0xad, 0xf0, 0x1e, 0x10, 0x1b, 0xa5, + + 0x2e, 0x08, 0x20, 0xfe, 0xa3, 0x28, 0x10, 0x0d, + 0xa5, 0x3e, 0x05, 0x3f, 0x05, 0x40, 0x05, 0x41, + + 0xf0, 0x03, 0x20, 0xc7, 0xa4, 0x20, 0xe7, 0xa3, + 0xa9, 0x40, 0x60, 0x4c, 0x0e, 0x8c, 0x20, 0xec, + + 0xad, 0xd0, 0xf8, 0xa5, 0x36, 0xf0, 0x1d, 0xad, + 0x00, 0x06, 0x4c, 0xd8, 0xae, 0x20, 0xad, 0xaf, + + 0xc0, 0x00, 0xd0, 0x10, 0x8a, 0x4c, 0xea, 0xae, + 0x20, 0xb5, 0xbf, 0xaa, 0xa9, 0x7f, 0x20, 0xf4, + + 0xff, 0x8a, 0xf0, 0xe6, 0xa9, 0xff, 0x85, 0x2a, + 0x85, 0x2b, 0x85, 0x2c, 0x85, 0x2d, 0xa9, 0x40, + + 0x60, 0x20, 0xe3, 0x92, 0xa2, 0x03, 0xb5, 0x2a, + 0x49, 0xff, 0x95, 0x2a, 0xca, 0x10, 0xf7, 0xa9, + + 0x40, 0x60, 0x20, 0x29, 0x9b, 0xd0, 0xb4, 0xe0, + 0x2c, 0xd0, 0x18, 0xe6, 0x1b, 0x20, 0xb2, 0xbd, + + 0x20, 0x29, 0x9b, 0xd0, 0xa6, 0xa9, 0x01, 0x85, + 0x2a, 0xe6, 0x1b, 0xe0, 0x29, 0xf0, 0x13, 0xe0, + + 0x2c, 0xf0, 0x03, 0x4c, 0xa2, 0x8a, 0x20, 0xb2, + 0xbd, 0x20, 0x56, 0xae, 0x20, 0xf0, 0x92, 0x20, + + 0xcb, 0xbd, 0xa0, 0x00, 0xa6, 0x2a, 0xd0, 0x02, + 0xa2, 0x01, 0x86, 0x2a, 0x8a, 0xca, 0x86, 0x2d, + + 0x18, 0x65, 0x04, 0x85, 0x37, 0x98, 0x65, 0x05, + 0x85, 0x38, 0xb1, 0x04, 0x38, 0xe5, 0x2d, 0x90, + + 0x21, 0xe5, 0x36, 0x90, 0x1d, 0x69, 0x00, 0x85, + 0x2b, 0x20, 0xdc, 0xbd, 0xa0, 0x00, 0xa6, 0x36, + + 0xf0, 0x0b, 0xb1, 0x37, 0xd9, 0x00, 0x06, 0xd0, + 0x10, 0xc8, 0xca, 0xd0, 0xf5, 0xa5, 0x2a, 0x4c, + + 0xd8, 0xae, 0x20, 0xdc, 0xbd, 0xa9, 0x00, 0xf0, + 0xf6, 0xe6, 0x2a, 0xc6, 0x2b, 0xf0, 0xf6, 0xe6, + + 0x37, 0xd0, 0xd9, 0xe6, 0x38, 0xd0, 0xd5, 0x4c, + 0x0e, 0x8c, 0x20, 0xec, 0xad, 0xf0, 0xf8, 0x30, + + 0x06, 0x24, 0x2d, 0x30, 0x1e, 0x10, 0x33, 0x20, + 0xda, 0xa1, 0x10, 0x0d, 0x30, 0x05, 0x20, 0xda, + + 0xa1, 0xf0, 0x06, 0xa5, 0x2e, 0x49, 0x80, 0x85, + 0x2e, 0xa9, 0xff, 0x60, 0x20, 0x02, 0xae, 0xf0, + + 0xd6, 0x30, 0xeb, 0x38, 0xa9, 0x00, 0xa8, 0xe5, + 0x2a, 0x85, 0x2a, 0x98, 0xe5, 0x2b, 0x85, 0x2b, + + 0x98, 0xe5, 0x2c, 0x85, 0x2c, 0x98, 0xe5, 0x2d, + 0x85, 0x2d, 0xa9, 0x40, 0x60, 0x20, 0x8c, 0x8a, + + 0xc9, 0x22, 0xf0, 0x15, 0xa2, 0x00, 0xb1, 0x19, + 0x9d, 0x00, 0x06, 0xc8, 0xe8, 0xc9, 0x0d, 0xf0, + + 0x04, 0xc9, 0x2c, 0xd0, 0xf1, 0x88, 0x4c, 0xe1, + 0xad, 0xa2, 0x00, 0xc8, 0xb1, 0x19, 0xc9, 0x0d, + + 0xf0, 0x17, 0xc8, 0x9d, 0x00, 0x06, 0xe8, 0xc9, + 0x22, 0xd0, 0xf1, 0xb1, 0x19, 0xc9, 0x22, 0xf0, + + 0xea, 0xca, 0x86, 0x36, 0x84, 0x1b, 0xa9, 0x00, + 0x60, 0x4c, 0x98, 0x8e, 0xa4, 0x1b, 0xe6, 0x1b, + + 0xb1, 0x19, 0xc9, 0x20, 0xf0, 0xf6, 0xc9, 0x2d, + 0xf0, 0x92, 0xc9, 0x22, 0xf0, 0xcb, 0xc9, 0x2b, + + 0xd0, 0x03, 0x20, 0x8c, 0x8a, 0xc9, 0x8e, 0x90, + 0x07, 0xc9, 0xc6, 0xb0, 0x36, 0x4c, 0xb1, 0x8b, + + 0xc9, 0x3f, 0xb0, 0x0c, 0xc9, 0x2e, 0xb0, 0x12, + 0xc9, 0x26, 0xf0, 0x51, 0xc9, 0x28, 0xf0, 0x36, + + 0xc6, 0x1b, 0x20, 0xdd, 0x95, 0xf0, 0x09, 0x4c, + 0x2c, 0xb3, 0x20, 0x7b, 0xa0, 0x90, 0x14, 0x60, + + 0xa5, 0x28, 0x29, 0x02, 0xd0, 0x0d, 0xb0, 0x0b, + 0x86, 0x1b, 0xad, 0x40, 0x04, 0xac, 0x41, 0x04, + + 0x4c, 0xea, 0xae, 0x00, 0x1a, 0x4e, 0x6f, 0x20, + 0x73, 0x75, 0x63, 0x68, 0x20, 0x76, 0x61, 0x72, + + 0x69, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x20, 0x29, + 0x9b, 0xe6, 0x1b, 0xe0, 0x29, 0xd0, 0x02, 0xa8, + + 0x60, 0x00, 0x1b, 0x4d, 0x69, 0x73, 0x73, 0x69, + 0x6e, 0x67, 0x20, 0x29, 0x00, 0xa2, 0x00, 0x86, + + 0x2a, 0x86, 0x2b, 0x86, 0x2c, 0x86, 0x2d, 0xa4, + 0x1b, 0xb1, 0x19, 0xc9, 0x30, 0x90, 0x23, 0xc9, + + 0x3a, 0x90, 0x0a, 0xe9, 0x37, 0xc9, 0x0a, 0x90, + 0x19, 0xc9, 0x10, 0xb0, 0x15, 0x0a, 0x0a, 0x0a, + + 0x0a, 0xa2, 0x03, 0x0a, 0x26, 0x2a, 0x26, 0x2b, + 0x26, 0x2c, 0x26, 0x2d, 0xca, 0x10, 0xf4, 0xc8, + + 0xd0, 0xd7, 0x8a, 0x10, 0x05, 0x84, 0x1b, 0xa9, + 0x40, 0x60, 0x00, 0x1c, 0x42, 0x61, 0x64, 0x20, + + 0x48, 0x45, 0x58, 0x00, 0xa2, 0x2a, 0xa0, 0x00, + 0xa9, 0x01, 0x20, 0xf1, 0xff, 0xa9, 0x40, 0x60, + + 0xa9, 0x00, 0xa4, 0x18, 0x4c, 0xea, 0xae, 0x4c, + 0x43, 0xae, 0xa9, 0x00, 0xf0, 0x0a, 0x4c, 0x0e, + + 0x8c, 0x20, 0xec, 0xad, 0xd0, 0xf8, 0xa5, 0x36, + 0xa0, 0x00, 0xf0, 0x0e, 0xa4, 0x1b, 0xb1, 0x19, + + 0xc9, 0x50, 0xd0, 0xe3, 0xe6, 0x1b, 0xa5, 0x12, + 0xa4, 0x13, 0x85, 0x2a, 0x84, 0x2b, 0xa9, 0x00, + + 0x85, 0x2c, 0x85, 0x2d, 0xa9, 0x40, 0x60, 0xa5, + 0x1e, 0x4c, 0xd8, 0xae, 0xa5, 0x00, 0xa4, 0x01, + + 0x4c, 0xea, 0xae, 0xa5, 0x06, 0xa4, 0x07, 0x4c, + 0xea, 0xae, 0xe6, 0x1b, 0x20, 0x56, 0xae, 0x20, + + 0xf0, 0x92, 0xa5, 0x2d, 0x30, 0x29, 0x05, 0x2c, + 0x05, 0x2b, 0xd0, 0x08, 0xa5, 0x2a, 0xf0, 0x4c, + + 0xc9, 0x01, 0xf0, 0x45, 0x20, 0xbe, 0xa2, 0x20, + 0x51, 0xbd, 0x20, 0x69, 0xaf, 0x20, 0x7e, 0xbd, + + 0x20, 0x06, 0xa6, 0x20, 0x03, 0xa3, 0x20, 0xe4, + 0xa3, 0x20, 0x22, 0x92, 0xa9, 0x40, 0x60, 0xa2, + + 0x0d, 0x20, 0x44, 0xbe, 0xa9, 0x40, 0x85, 0x11, + 0x60, 0xa4, 0x1b, 0xb1, 0x19, 0xc9, 0x28, 0xf0, + + 0xb9, 0x20, 0x87, 0xaf, 0xa2, 0x0d, 0xb5, 0x00, + 0x85, 0x2a, 0xb5, 0x01, 0x85, 0x2b, 0xb5, 0x02, + + 0x85, 0x2c, 0xb5, 0x03, 0x85, 0x2d, 0xa9, 0x40, + 0x60, 0x20, 0x87, 0xaf, 0xa2, 0x00, 0x86, 0x2e, + + 0x86, 0x2f, 0x86, 0x35, 0xa9, 0x80, 0x85, 0x30, + 0xb5, 0x0d, 0x95, 0x31, 0xe8, 0xe0, 0x04, 0xd0, + + 0xf7, 0x20, 0x59, 0xa6, 0xa9, 0xff, 0x60, 0xa0, + 0x20, 0xa5, 0x0f, 0x4a, 0x4a, 0x4a, 0x45, 0x11, + + 0x6a, 0x26, 0x0d, 0x26, 0x0e, 0x26, 0x0f, 0x26, + 0x10, 0x26, 0x11, 0x88, 0xd0, 0xeb, 0x60, 0xa4, + + 0x09, 0xa5, 0x08, 0x4c, 0xea, 0xae, 0xa0, 0x00, + 0xb1, 0xfd, 0x4c, 0xea, 0xae, 0x20, 0xe3, 0x92, + + 0xa9, 0x81, 0xa6, 0x2a, 0xa4, 0x2b, 0x4c, 0xf4, + 0xff, 0x20, 0xe0, 0xff, 0x4c, 0xd8, 0xae, 0x20, + + 0xe0, 0xff, 0x8d, 0x00, 0x06, 0xa9, 0x01, 0x85, + 0x36, 0xa9, 0x00, 0x60, 0x20, 0x29, 0x9b, 0xd0, + + 0x62, 0xe0, 0x2c, 0xd0, 0x61, 0xe6, 0x1b, 0x20, + 0xb2, 0xbd, 0x20, 0x56, 0xae, 0x20, 0xf0, 0x92, + + 0x20, 0xcb, 0xbd, 0xa5, 0x2a, 0xc5, 0x36, 0xb0, + 0x02, 0x85, 0x36, 0xa9, 0x00, 0x60, 0x20, 0x29, + + 0x9b, 0xd0, 0x40, 0xe0, 0x2c, 0xd0, 0x3f, 0xe6, + 0x1b, 0x20, 0xb2, 0xbd, 0x20, 0x56, 0xae, 0x20, + + 0xf0, 0x92, 0x20, 0xcb, 0xbd, 0xa5, 0x36, 0x38, + 0xe5, 0x2a, 0x90, 0x17, 0xf0, 0x17, 0xaa, 0xa5, + + 0x2a, 0x85, 0x36, 0xf0, 0x10, 0xa0, 0x00, 0xbd, + 0x00, 0x06, 0x99, 0x00, 0x06, 0xe8, 0xc8, 0xc6, + + 0x2a, 0xd0, 0xf4, 0xa9, 0x00, 0x60, 0x20, 0xad, + 0xaf, 0x8a, 0xc0, 0x00, 0xf0, 0x94, 0xa9, 0x00, + + 0x85, 0x36, 0x60, 0x4c, 0x0e, 0x8c, 0x4c, 0xa2, + 0x8a, 0x20, 0x29, 0x9b, 0xd0, 0xf5, 0xe0, 0x2c, + + 0xd0, 0xf4, 0x20, 0xb2, 0xbd, 0xe6, 0x1b, 0x20, + 0xdd, 0x92, 0xa5, 0x2a, 0x48, 0xa9, 0xff, 0x85, + + 0x2a, 0xe6, 0x1b, 0xe0, 0x29, 0xf0, 0x0a, 0xe0, + 0x2c, 0xd0, 0xdb, 0x20, 0x56, 0xae, 0x20, 0xf0, + + 0x92, 0x20, 0xcb, 0xbd, 0x68, 0xa8, 0x18, 0xf0, + 0x06, 0xe5, 0x36, 0xb0, 0xc1, 0x88, 0x98, 0x85, + + 0x2c, 0xaa, 0xa0, 0x00, 0xa5, 0x36, 0x38, 0xe5, + 0x2c, 0xc5, 0x2a, 0xb0, 0x02, 0x85, 0x2a, 0xa5, + + 0x2a, 0xf0, 0xab, 0xbd, 0x00, 0x06, 0x99, 0x00, + 0x06, 0xc8, 0xe8, 0xc4, 0x2a, 0xd0, 0xf4, 0x84, + + 0x36, 0xa9, 0x00, 0x60, 0x20, 0x8c, 0x8a, 0xa0, + 0xff, 0xc9, 0x7e, 0xf0, 0x04, 0xa0, 0x00, 0xc6, + + 0x1b, 0x98, 0x48, 0x20, 0xec, 0xad, 0xf0, 0x17, + 0xa8, 0x68, 0x85, 0x15, 0xad, 0x03, 0x04, 0xd0, + + 0x08, 0x85, 0x37, 0x20, 0xf9, 0x9e, 0xa9, 0x00, + 0x60, 0x20, 0xdf, 0x9e, 0xa9, 0x00, 0x60, 0x4c, + + 0x0e, 0x8c, 0x20, 0xdd, 0x92, 0x20, 0x94, 0xbd, + 0x20, 0xae, 0x8a, 0x20, 0x56, 0xae, 0xd0, 0xef, + + 0x20, 0xea, 0xbd, 0xa4, 0x36, 0xf0, 0x1e, 0xa5, + 0x2a, 0xf0, 0x1d, 0xc6, 0x2a, 0xf0, 0x16, 0xa2, + + 0x00, 0xbd, 0x00, 0x06, 0x99, 0x00, 0x06, 0xe8, + 0xc8, 0xf0, 0x10, 0xe4, 0x36, 0x90, 0xf2, 0xc6, + + 0x2a, 0xd0, 0xec, 0x84, 0x36, 0xa9, 0x00, 0x60, + 0x85, 0x36, 0x60, 0x4c, 0x03, 0x9c, 0x68, 0x85, + + 0x0c, 0x68, 0x85, 0x0b, 0x00, 0x1d, 0x4e, 0x6f, + 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, 0xa4, 0x2f, + + 0xf2, 0x00, 0xa5, 0x18, 0x85, 0x0c, 0xa9, 0x00, + 0x85, 0x0b, 0xa0, 0x01, 0xb1, 0x0b, 0x30, 0xde, + + 0xa0, 0x03, 0xc8, 0xb1, 0x0b, 0xc9, 0x20, 0xf0, + 0xf9, 0xc9, 0xdd, 0xf0, 0x0f, 0xa0, 0x03, 0xb1, + + 0x0b, 0x18, 0x65, 0x0b, 0x85, 0x0b, 0x90, 0xe2, + 0xe6, 0x0c, 0xb0, 0xde, 0xc8, 0x84, 0x0a, 0x20, + + 0x97, 0x8a, 0x98, 0xaa, 0x18, 0x65, 0x0b, 0xa4, + 0x0c, 0x90, 0x02, 0xc8, 0x18, 0xe9, 0x00, 0x85, + + 0x3c, 0x98, 0xe9, 0x00, 0x85, 0x3d, 0xa0, 0x00, + 0xc8, 0xe8, 0xb1, 0x3c, 0xd1, 0x37, 0xd0, 0xcd, + + 0xc4, 0x39, 0xd0, 0xf4, 0xc8, 0xb1, 0x3c, 0x20, + 0x26, 0x89, 0xb0, 0xc1, 0x8a, 0xa8, 0x20, 0x6d, + + 0x98, 0x20, 0xed, 0x94, 0xa2, 0x01, 0x20, 0x31, + 0x95, 0xa0, 0x00, 0xa5, 0x0b, 0x91, 0x02, 0xc8, + + 0xa5, 0x0c, 0x91, 0x02, 0x20, 0x39, 0x95, 0x4c, + 0xf4, 0xb1, 0x00, 0x1e, 0x42, 0x61, 0x64, 0x20, + + 0x63, 0x61, 0x6c, 0x6c, 0x00, 0xa9, 0xa4, 0x85, + 0x27, 0xba, 0x8a, 0x18, 0x65, 0x04, 0x20, 0x2e, + + 0xbe, 0xa0, 0x00, 0x8a, 0x91, 0x04, 0xe8, 0xc8, + 0xbd, 0x00, 0x01, 0x91, 0x04, 0xe0, 0xff, 0xd0, + + 0xf5, 0x9a, 0xa5, 0x27, 0x48, 0xa5, 0x0a, 0x48, + 0xa5, 0x0b, 0x48, 0xa5, 0x0c, 0x48, 0xa5, 0x1b, + + 0xaa, 0x18, 0x65, 0x19, 0xa4, 0x1a, 0x90, 0x02, + 0xc8, 0x18, 0xe9, 0x01, 0x85, 0x37, 0x98, 0xe9, + + 0x00, 0x85, 0x38, 0xa0, 0x02, 0x20, 0x5b, 0x95, + 0xc0, 0x02, 0xf0, 0xae, 0x86, 0x1b, 0x88, 0x84, + + 0x39, 0x20, 0x5b, 0x94, 0xd0, 0x03, 0x4c, 0x12, + 0xb1, 0xa0, 0x00, 0xb1, 0x2a, 0x85, 0x0b, 0xc8, + + 0xb1, 0x2a, 0x85, 0x0c, 0xa9, 0x00, 0x48, 0x85, + 0x0a, 0x20, 0x97, 0x8a, 0xc9, 0x28, 0xf0, 0x4d, + + 0xc6, 0x0a, 0xa5, 0x1b, 0x48, 0xa5, 0x19, 0x48, + 0xa5, 0x1a, 0x48, 0x20, 0xa3, 0x8b, 0x68, 0x85, + + 0x1a, 0x68, 0x85, 0x19, 0x68, 0x85, 0x1b, 0x68, + 0xf0, 0x0c, 0x85, 0x3f, 0x20, 0x0b, 0xbe, 0x20, + + 0xc1, 0x8c, 0xc6, 0x3f, 0xd0, 0xf6, 0x68, 0x85, + 0x0c, 0x68, 0x85, 0x0b, 0x68, 0x85, 0x0a, 0x68, + + 0xa0, 0x00, 0xb1, 0x04, 0xaa, 0x9a, 0xc8, 0xe8, + 0xb1, 0x04, 0x9d, 0x00, 0x01, 0xe0, 0xff, 0xd0, + + 0xf5, 0x98, 0x65, 0x04, 0x85, 0x04, 0x90, 0x02, + 0xe6, 0x05, 0xa5, 0x27, 0x60, 0xa5, 0x1b, 0x48, + + 0xa5, 0x19, 0x48, 0xa5, 0x1a, 0x48, 0x20, 0x82, + 0x95, 0xf0, 0x5a, 0xa5, 0x1b, 0x85, 0x0a, 0x68, + + 0x85, 0x1a, 0x68, 0x85, 0x19, 0x68, 0x85, 0x1b, + 0x68, 0xaa, 0xa5, 0x2c, 0x48, 0xa5, 0x2b, 0x48, + + 0xa5, 0x2a, 0x48, 0xe8, 0x8a, 0x48, 0x20, 0x0d, + 0xb3, 0x20, 0x97, 0x8a, 0xc9, 0x2c, 0xf0, 0xcd, + + 0xc9, 0x29, 0xd0, 0x31, 0xa9, 0x00, 0x48, 0x20, + 0x8c, 0x8a, 0xc9, 0x28, 0xd0, 0x27, 0x20, 0x29, + + 0x9b, 0x20, 0x90, 0xbd, 0xa5, 0x27, 0x85, 0x2d, + 0x20, 0x94, 0xbd, 0x68, 0xaa, 0xe8, 0x8a, 0x48, + + 0x20, 0x8c, 0x8a, 0xc9, 0x2c, 0xf0, 0xe7, 0xc9, + 0x29, 0xd0, 0x0a, 0x68, 0x68, 0x85, 0x4d, 0x85, + + 0x4e, 0xe4, 0x4d, 0xf0, 0x15, 0xa2, 0xfb, 0x9a, + 0x68, 0x85, 0x0c, 0x68, 0x85, 0x0b, 0x00, 0x1f, + + 0x41, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, + 0x73, 0x00, 0x20, 0xea, 0xbd, 0x68, 0x85, 0x2a, + + 0x68, 0x85, 0x2b, 0x68, 0x85, 0x2c, 0x30, 0x21, + 0xa5, 0x2d, 0xf0, 0xd9, 0x85, 0x27, 0xa2, 0x37, + + 0x20, 0x44, 0xbe, 0xa5, 0x27, 0x10, 0x09, 0x20, + 0x7e, 0xbd, 0x20, 0xb5, 0xa3, 0x4c, 0xf3, 0xb2, + + 0x20, 0xea, 0xbd, 0x20, 0xb7, 0xb4, 0x4c, 0x03, + 0xb3, 0xa5, 0x2d, 0xd0, 0xb8, 0x20, 0xcb, 0xbd, + + 0x20, 0x21, 0x8c, 0xc6, 0x4d, 0xd0, 0xc3, 0xa5, + 0x4e, 0x48, 0x4c, 0x02, 0xb2, 0xa4, 0x2c, 0xc0, + + 0x04, 0xd0, 0x05, 0xa2, 0x37, 0x20, 0x44, 0xbe, + 0x20, 0x2c, 0xb3, 0x08, 0x20, 0x90, 0xbd, 0x28, + + 0xf0, 0x07, 0x30, 0x05, 0xa2, 0x37, 0x20, 0x56, + 0xaf, 0x4c, 0x94, 0xbd, 0xa4, 0x2c, 0x30, 0x54, + + 0xf0, 0x1d, 0xc0, 0x05, 0xf0, 0x1e, 0xa0, 0x03, + 0xb1, 0x2a, 0x85, 0x2d, 0x88, 0xb1, 0x2a, 0x85, + + 0x2c, 0x88, 0xb1, 0x2a, 0xaa, 0x88, 0xb1, 0x2a, + 0x85, 0x2a, 0x86, 0x2b, 0xa9, 0x40, 0x60, 0xb1, + + 0x2a, 0x4c, 0xea, 0xae, 0x88, 0xb1, 0x2a, 0x85, + 0x34, 0x88, 0xb1, 0x2a, 0x85, 0x33, 0x88, 0xb1, + + 0x2a, 0x85, 0x32, 0x88, 0xb1, 0x2a, 0x85, 0x2e, + 0x88, 0xb1, 0x2a, 0x85, 0x30, 0x84, 0x35, 0x84, + + 0x2f, 0x05, 0x2e, 0x05, 0x32, 0x05, 0x33, 0x05, + 0x34, 0xf0, 0x04, 0xa5, 0x2e, 0x09, 0x80, 0x85, + + 0x31, 0xa9, 0xff, 0x60, 0xc0, 0x80, 0xf0, 0x1f, + 0xa0, 0x03, 0xb1, 0x2a, 0x85, 0x36, 0xf0, 0x16, + + 0xa0, 0x01, 0xb1, 0x2a, 0x85, 0x38, 0x88, 0xb1, + 0x2a, 0x85, 0x37, 0xa4, 0x36, 0x88, 0xb1, 0x37, + + 0x99, 0x00, 0x06, 0x98, 0xd0, 0xf7, 0x60, 0xa5, + 0x2b, 0xf0, 0x15, 0xa0, 0x00, 0xb1, 0x2a, 0x99, + + 0x00, 0x06, 0x49, 0x0d, 0xf0, 0x04, 0xc8, 0xd0, + 0xf4, 0x98, 0x84, 0x36, 0x60, 0x20, 0xe3, 0x92, + + 0xa5, 0x2a, 0x4c, 0xc2, 0xaf, 0xa0, 0x00, 0x84, + 0x08, 0x84, 0x09, 0xa6, 0x18, 0x86, 0x38, 0x84, + + 0x37, 0xa6, 0x0c, 0xe0, 0x07, 0xf0, 0x2a, 0xa6, + 0x0b, 0x20, 0x42, 0x89, 0xc9, 0x0d, 0xd0, 0x19, + + 0xe4, 0x37, 0xa5, 0x0c, 0xe5, 0x38, 0x90, 0x19, + 0x20, 0x42, 0x89, 0x09, 0x00, 0x30, 0x12, 0x85, + + 0x09, 0x20, 0x42, 0x89, 0x85, 0x08, 0x20, 0x42, + 0x89, 0xe4, 0x37, 0xa5, 0x0c, 0xe5, 0x38, 0xb0, + + 0xd8, 0x60, 0x20, 0xc5, 0xb3, 0x84, 0x20, 0xb1, + 0xfd, 0xd0, 0x08, 0xa9, 0x33, 0x85, 0x16, 0xa9, + + 0xb4, 0x85, 0x17, 0xa5, 0x16, 0x85, 0x0b, 0xa5, + 0x17, 0x85, 0x0c, 0x20, 0x3a, 0xbd, 0xaa, 0x86, + + 0x0a, 0xa9, 0xda, 0x20, 0xf4, 0xff, 0xa9, 0x7e, + 0x20, 0xf4, 0xff, 0xa2, 0xff, 0x86, 0x28, 0x9a, + + 0x4c, 0xa3, 0x8b, 0xf6, 0x3a, 0xe7, 0x9e, 0xf1, + 0x22, 0x20, 0x61, 0x74, 0x20, 0x6c, 0x69, 0x6e, + + 0x65, 0x20, 0x22, 0x3b, 0x9e, 0x3a, 0xe0, 0x8b, + 0xf1, 0x3a, 0xe0, 0x0d, 0x20, 0x21, 0x88, 0xa2, + + 0x03, 0xa5, 0x2a, 0x48, 0xa5, 0x2b, 0x48, 0x8a, + 0x48, 0x20, 0xda, 0x92, 0x68, 0xaa, 0xca, 0xd0, + + 0xf0, 0x20, 0x52, 0x98, 0xa5, 0x2a, 0x85, 0x3d, + 0xa5, 0x2b, 0x85, 0x3e, 0xa0, 0x07, 0xa2, 0x05, + + 0xd0, 0x1d, 0x20, 0x21, 0x88, 0xa2, 0x0d, 0xa5, + 0x2a, 0x48, 0x8a, 0x48, 0x20, 0xda, 0x92, 0x68, + + 0xaa, 0xca, 0xd0, 0xf3, 0x20, 0x52, 0x98, 0xa5, + 0x2a, 0x85, 0x44, 0xa2, 0x0c, 0xa0, 0x08, 0x68, + + 0x95, 0x37, 0xca, 0x10, 0xfa, 0x98, 0xa2, 0x37, + 0xa0, 0x00, 0x20, 0xf1, 0xff, 0x4c, 0x9b, 0x8b, + + 0x20, 0x21, 0x88, 0x20, 0x52, 0x98, 0xa4, 0x2a, + 0x88, 0x84, 0x23, 0x4c, 0x9b, 0x8b, 0x4c, 0x0e, + + 0x8c, 0x20, 0x29, 0x9b, 0x20, 0x0b, 0xbe, 0xa5, + 0x39, 0xc9, 0x05, 0xf0, 0x23, 0xa5, 0x27, 0xf0, + + 0xed, 0x10, 0x03, 0x20, 0xe4, 0xa3, 0xa0, 0x00, + 0xa5, 0x2a, 0x91, 0x37, 0xa5, 0x39, 0xf0, 0x0f, + + 0xa5, 0x2b, 0xc8, 0x91, 0x37, 0xa5, 0x2c, 0xc8, + 0x91, 0x37, 0xa5, 0x2d, 0xc8, 0x91, 0x37, 0x60, + + 0xa5, 0x27, 0xf0, 0xca, 0x30, 0x03, 0x20, 0xbe, + 0xa2, 0xa0, 0x00, 0xa5, 0x30, 0x91, 0x37, 0xc8, + + 0xa5, 0x2e, 0x29, 0x80, 0x85, 0x2e, 0xa5, 0x31, + 0x29, 0x7f, 0x05, 0x2e, 0x91, 0x37, 0xc8, 0xa5, + + 0x32, 0x91, 0x37, 0xc8, 0xa5, 0x33, 0x91, 0x37, + 0xc8, 0xa5, 0x34, 0x91, 0x37, 0x60, 0x85, 0x37, + + 0xc9, 0x80, 0x90, 0x44, 0xa9, 0x71, 0x85, 0x38, + 0xa9, 0x80, 0x85, 0x39, 0x84, 0x3a, 0xa0, 0x00, + + 0xc8, 0xb1, 0x38, 0x10, 0xfb, 0xc5, 0x37, 0xf0, + 0x0d, 0xc8, 0x98, 0x38, 0x65, 0x38, 0x85, 0x38, + + 0x90, 0xec, 0xe6, 0x39, 0xb0, 0xe8, 0xa0, 0x00, + 0xb1, 0x38, 0x30, 0x06, 0x20, 0x58, 0xb5, 0xc8, + + 0xd0, 0xf6, 0xa4, 0x3a, 0x60, 0x48, 0x4a, 0x4a, + 0x4a, 0x4a, 0x20, 0x50, 0xb5, 0x68, 0x29, 0x0f, + + 0xc9, 0x0a, 0x90, 0x02, 0x69, 0x06, 0x69, 0x30, + 0xc9, 0x0d, 0xd0, 0x0b, 0x20, 0xee, 0xff, 0x4c, + + 0x28, 0xbc, 0x20, 0x45, 0xb5, 0xa9, 0x20, 0x48, + 0xa5, 0x23, 0xc5, 0x1e, 0xb0, 0x03, 0x20, 0x25, + + 0xbc, 0x68, 0xe6, 0x1e, 0x6c, 0x0e, 0x02, 0x25, + 0x1f, 0xf0, 0x0e, 0x8a, 0xf0, 0x0b, 0x30, 0xe5, + + 0x20, 0x65, 0xb5, 0x20, 0x58, 0xb5, 0xca, 0xd0, + 0xf7, 0x60, 0xe6, 0x0a, 0x20, 0x1d, 0x9b, 0x20, + + 0x4c, 0x98, 0x20, 0xee, 0x92, 0xa5, 0x2a, 0x85, + 0x1f, 0x4c, 0xf6, 0x8a, 0xc8, 0xb1, 0x0b, 0xc9, + + 0x4f, 0xf0, 0xe7, 0xa9, 0x00, 0x85, 0x3b, 0x85, + 0x3c, 0x20, 0xd8, 0xae, 0x20, 0xdf, 0x97, 0x08, + + 0x20, 0x94, 0xbd, 0xa9, 0xff, 0x85, 0x2a, 0xa9, + 0x7f, 0x85, 0x2b, 0x28, 0x90, 0x11, 0x20, 0x97, + + 0x8a, 0xc9, 0x2c, 0xf0, 0x13, 0x20, 0xea, 0xbd, + 0x20, 0x94, 0xbd, 0xc6, 0x0a, 0x10, 0x0c, 0x20, + + 0x97, 0x8a, 0xc9, 0x2c, 0xf0, 0x02, 0xc6, 0x0a, + 0x20, 0xdf, 0x97, 0xa5, 0x2a, 0x85, 0x31, 0xa5, + + 0x2b, 0x85, 0x32, 0x20, 0x57, 0x98, 0x20, 0x6f, + 0xbe, 0x20, 0xea, 0xbd, 0x20, 0x70, 0x99, 0xa5, + + 0x3d, 0x85, 0x0b, 0xa5, 0x3e, 0x85, 0x0c, 0x90, + 0x16, 0x88, 0xb0, 0x06, 0x20, 0x25, 0xbc, 0x20, + + 0x6d, 0x98, 0xb1, 0x0b, 0x85, 0x2b, 0xc8, 0xb1, + 0x0b, 0x85, 0x2a, 0xc8, 0xc8, 0x84, 0x0a, 0xa5, + + 0x2a, 0x18, 0xe5, 0x31, 0xa5, 0x2b, 0xe5, 0x32, + 0x90, 0x03, 0x4c, 0xf6, 0x8a, 0x20, 0x23, 0x99, + + 0xa2, 0xff, 0x86, 0x4d, 0xa9, 0x01, 0x20, 0x77, + 0xb5, 0xa6, 0x3b, 0xa9, 0x02, 0x20, 0x77, 0xb5, + + 0xa6, 0x3c, 0xa9, 0x04, 0x20, 0x77, 0xb5, 0xa4, + 0x0a, 0xb1, 0x0b, 0xc9, 0x0d, 0xf0, 0xbd, 0xc9, + + 0x22, 0xd0, 0x0e, 0xa9, 0xff, 0x45, 0x4d, 0x85, + 0x4d, 0xa9, 0x22, 0x20, 0x58, 0xb5, 0xc8, 0xd0, + + 0xe8, 0x24, 0x4d, 0x10, 0xf6, 0xc9, 0x8d, 0xd0, + 0x0f, 0x20, 0xeb, 0x97, 0x84, 0x0a, 0xa9, 0x00, + + 0x85, 0x14, 0x20, 0x1f, 0x99, 0x4c, 0x37, 0xb6, + 0xc9, 0xe3, 0xd0, 0x02, 0xe6, 0x3b, 0xc9, 0xed, + + 0xd0, 0x06, 0xa6, 0x3b, 0xf0, 0x02, 0xc6, 0x3b, + 0xc9, 0xf5, 0xd0, 0x02, 0xe6, 0x3c, 0xc9, 0xfd, + + 0xd0, 0x06, 0xa6, 0x3c, 0xf0, 0x02, 0xc6, 0x3c, + 0x20, 0x0e, 0xb5, 0xc8, 0xd0, 0xab, 0x00, 0x20, + + 0x4e, 0x6f, 0x20, 0xe3, 0x00, 0x20, 0xc9, 0x95, + 0xd0, 0x09, 0xa6, 0x26, 0xf0, 0xf0, 0xb0, 0x37, + + 0x4c, 0x2a, 0x98, 0xb0, 0xfb, 0xa6, 0x26, 0xf0, + 0xe5, 0xa5, 0x2a, 0xdd, 0xf1, 0x04, 0xd0, 0x0e, + + 0xa5, 0x2b, 0xdd, 0xf2, 0x04, 0xd0, 0x07, 0xa5, + 0x2c, 0xdd, 0xf3, 0x04, 0xf0, 0x19, 0x8a, 0x38, + + 0xe9, 0x0f, 0xaa, 0x86, 0x26, 0xd0, 0xe2, 0x00, + 0x21, 0x43, 0x61, 0x6e, 0x27, 0x74, 0x20, 0x4d, + + 0x61, 0x74, 0x63, 0x68, 0x20, 0xe3, 0x00, 0xbd, + 0xf1, 0x04, 0x85, 0x2a, 0xbd, 0xf2, 0x04, 0x85, + + 0x2b, 0xbc, 0xf3, 0x04, 0xc0, 0x05, 0xf0, 0x7e, + 0xa0, 0x00, 0xb1, 0x2a, 0x7d, 0xf4, 0x04, 0x91, + + 0x2a, 0x85, 0x37, 0xc8, 0xb1, 0x2a, 0x7d, 0xf5, + 0x04, 0x91, 0x2a, 0x85, 0x38, 0xc8, 0xb1, 0x2a, + + 0x7d, 0xf6, 0x04, 0x91, 0x2a, 0x85, 0x39, 0xc8, + 0xb1, 0x2a, 0x7d, 0xf7, 0x04, 0x91, 0x2a, 0xa8, + + 0xa5, 0x37, 0x38, 0xfd, 0xf9, 0x04, 0x85, 0x37, + 0xa5, 0x38, 0xfd, 0xfa, 0x04, 0x85, 0x38, 0xa5, + + 0x39, 0xfd, 0xfb, 0x04, 0x85, 0x39, 0x98, 0xfd, + 0xfc, 0x04, 0x05, 0x37, 0x05, 0x38, 0x05, 0x39, + + 0xf0, 0x0f, 0x98, 0x5d, 0xf7, 0x04, 0x5d, 0xfc, + 0x04, 0x10, 0x04, 0xb0, 0x04, 0x90, 0x12, 0xb0, + + 0x10, 0xbc, 0xfe, 0x04, 0xbd, 0xff, 0x04, 0x84, + 0x0b, 0x85, 0x0c, 0x20, 0x77, 0x98, 0x4c, 0xa3, + + 0x8b, 0xa5, 0x26, 0x38, 0xe9, 0x0f, 0x85, 0x26, + 0xa4, 0x1b, 0x84, 0x0a, 0x20, 0x97, 0x8a, 0xc9, + + 0x2c, 0xd0, 0x3e, 0x4c, 0x95, 0xb6, 0x20, 0x54, + 0xb3, 0xa5, 0x26, 0x18, 0x69, 0xf4, 0x85, 0x4b, + + 0xa9, 0x05, 0x85, 0x4c, 0x20, 0x00, 0xa5, 0xa5, + 0x2a, 0x85, 0x37, 0xa5, 0x2b, 0x85, 0x38, 0x20, + + 0xe9, 0xb4, 0xa5, 0x26, 0x85, 0x27, 0x18, 0x69, + 0xf9, 0x85, 0x4b, 0xa9, 0x05, 0x85, 0x4c, 0x20, + + 0x5f, 0x9a, 0xf0, 0xad, 0xbd, 0xf5, 0x04, 0x30, + 0x04, 0xb0, 0xa6, 0x90, 0xb4, 0x90, 0xa2, 0xb0, + + 0xb0, 0x4c, 0x96, 0x8b, 0x00, 0x22, 0xe3, 0x20, + 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, + + 0x00, 0x23, 0x54, 0x6f, 0x6f, 0x20, 0x6d, 0x61, + 0x6e, 0x79, 0x20, 0xe3, 0x73, 0x00, 0x24, 0x4e, + + 0x6f, 0x20, 0xb8, 0x00, 0x20, 0x82, 0x95, 0xf0, + 0xdb, 0xb0, 0xd9, 0x20, 0x94, 0xbd, 0x20, 0x41, + + 0x98, 0x20, 0xb1, 0xb4, 0xa4, 0x26, 0xc0, 0x96, + 0xb0, 0xd6, 0xa5, 0x37, 0x99, 0x00, 0x05, 0xa5, + + 0x38, 0x99, 0x01, 0x05, 0xa5, 0x39, 0x99, 0x02, + 0x05, 0xaa, 0x20, 0x8c, 0x8a, 0xc9, 0xb8, 0xd0, + + 0xcc, 0xe0, 0x05, 0xf0, 0x5a, 0x20, 0xdd, 0x92, + 0xa4, 0x26, 0xa5, 0x2a, 0x99, 0x08, 0x05, 0xa5, + + 0x2b, 0x99, 0x09, 0x05, 0xa5, 0x2c, 0x99, 0x0a, + 0x05, 0xa5, 0x2d, 0x99, 0x0b, 0x05, 0xa9, 0x01, + + 0x20, 0xd8, 0xae, 0x20, 0x8c, 0x8a, 0xc9, 0x88, + 0xd0, 0x05, 0x20, 0xdd, 0x92, 0xa4, 0x1b, 0x84, + + 0x0a, 0xa4, 0x26, 0xa5, 0x2a, 0x99, 0x03, 0x05, + 0xa5, 0x2b, 0x99, 0x04, 0x05, 0xa5, 0x2c, 0x99, + + 0x05, 0x05, 0xa5, 0x2d, 0x99, 0x06, 0x05, 0x20, + 0x80, 0x98, 0xa4, 0x26, 0xa5, 0x0b, 0x99, 0x0d, + + 0x05, 0xa5, 0x0c, 0x99, 0x0e, 0x05, 0x18, 0x98, + 0x69, 0x0f, 0x85, 0x26, 0x4c, 0xa3, 0x8b, 0x20, + + 0x29, 0x9b, 0x20, 0xfd, 0x92, 0xa5, 0x26, 0x18, + 0x69, 0x08, 0x85, 0x4b, 0xa9, 0x05, 0x85, 0x4c, + + 0x20, 0x8d, 0xa3, 0x20, 0x99, 0xa6, 0x20, 0x8c, + 0x8a, 0xc9, 0x88, 0xd0, 0x08, 0x20, 0x29, 0x9b, + + 0x20, 0xfd, 0x92, 0xa4, 0x1b, 0x84, 0x0a, 0xa5, + 0x26, 0x18, 0x69, 0x03, 0x85, 0x4b, 0xa9, 0x05, + + 0x85, 0x4c, 0x20, 0x8d, 0xa3, 0x4c, 0x37, 0xb8, + 0x20, 0x9a, 0xb9, 0x20, 0x57, 0x98, 0xa4, 0x25, + + 0xc0, 0x1a, 0xb0, 0x0e, 0xa5, 0x0b, 0x99, 0xcc, + 0x05, 0xa5, 0x0c, 0x99, 0xe6, 0x05, 0xe6, 0x25, + + 0x90, 0x30, 0x00, 0x25, 0x54, 0x6f, 0x6f, 0x20, + 0x6d, 0x61, 0x6e, 0x79, 0x20, 0xe4, 0x73, 0x00, + + 0x26, 0x4e, 0x6f, 0x20, 0xe4, 0x00, 0x20, 0x57, + 0x98, 0xa6, 0x25, 0xf0, 0xf2, 0xc6, 0x25, 0xbc, + + 0xcb, 0x05, 0xbd, 0xe5, 0x05, 0x84, 0x0b, 0x85, + 0x0c, 0x4c, 0x9b, 0x8b, 0x20, 0x9a, 0xb9, 0x20, + + 0x57, 0x98, 0xa5, 0x20, 0xf0, 0x03, 0x20, 0x05, + 0x99, 0xa4, 0x3d, 0xa5, 0x3e, 0x84, 0x0b, 0x85, + + 0x0c, 0x4c, 0xa3, 0x8b, 0x20, 0x57, 0x98, 0xa9, + 0x33, 0x85, 0x16, 0xa9, 0xb4, 0x85, 0x17, 0x4c, + + 0x9b, 0x8b, 0x20, 0x97, 0x8a, 0xc9, 0x87, 0xf0, + 0xeb, 0xa4, 0x0a, 0x88, 0x20, 0x6d, 0x98, 0xa5, + + 0x0b, 0x85, 0x16, 0xa5, 0x0c, 0x85, 0x17, 0x4c, + 0x7d, 0x8b, 0x00, 0x27, 0xee, 0x20, 0x73, 0x79, + + 0x6e, 0x74, 0x61, 0x78, 0x00, 0x20, 0x97, 0x8a, + 0xc9, 0x85, 0xf0, 0xd6, 0xc6, 0x0a, 0x20, 0x1d, + + 0x9b, 0x20, 0xf0, 0x92, 0xa4, 0x1b, 0xc8, 0x84, + 0x0a, 0xe0, 0xe5, 0xf0, 0x04, 0xe0, 0xe4, 0xd0, + + 0xd9, 0x8a, 0x48, 0xa5, 0x2b, 0x05, 0x2c, 0x05, + 0x2d, 0xd0, 0x42, 0xa6, 0x2a, 0xf0, 0x3e, 0xca, + + 0xf0, 0x1a, 0xa4, 0x0a, 0xb1, 0x0b, 0xc8, 0xc9, + 0x0d, 0xf0, 0x32, 0xc9, 0x3a, 0xf0, 0x2e, 0xc9, + + 0x8b, 0xf0, 0x2a, 0xc9, 0x2c, 0xd0, 0xed, 0xca, + 0xd0, 0xea, 0x84, 0x0a, 0x20, 0x9a, 0xb9, 0x68, + + 0xc9, 0xe4, 0xf0, 0x06, 0x20, 0x77, 0x98, 0x4c, + 0xd2, 0xb8, 0xa4, 0x0a, 0xb1, 0x0b, 0xc8, 0xc9, + + 0x0d, 0xf0, 0x04, 0xc9, 0x3a, 0xd0, 0xf5, 0x88, + 0x84, 0x0a, 0x4c, 0x8b, 0xb8, 0xa4, 0x0a, 0x68, + + 0xb1, 0x0b, 0xc8, 0xc9, 0x8b, 0xf0, 0x0e, 0xc9, + 0x0d, 0xd0, 0xf5, 0x00, 0x28, 0xee, 0x20, 0x72, + + 0x61, 0x6e, 0x67, 0x65, 0x00, 0x84, 0x0a, 0x4c, + 0xe3, 0x98, 0x20, 0xdf, 0x97, 0xb0, 0x10, 0x20, + + 0x1d, 0x9b, 0x20, 0xf0, 0x92, 0xa5, 0x1b, 0x85, + 0x0a, 0xa5, 0x2b, 0x29, 0x7f, 0x85, 0x2b, 0x20, + + 0x70, 0x99, 0xb0, 0x01, 0x60, 0x00, 0x29, 0x4e, + 0x6f, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, 0x6c, + + 0x69, 0x6e, 0x65, 0x00, 0x4c, 0x0e, 0x8c, 0x4c, + 0x2a, 0x98, 0x84, 0x0a, 0x4c, 0x98, 0x8b, 0xc6, + + 0x0a, 0x20, 0xa9, 0xbf, 0xa5, 0x1b, 0x85, 0x0a, + 0x84, 0x4d, 0x20, 0x97, 0x8a, 0xc9, 0x2c, 0xd0, + + 0xe9, 0xa5, 0x4d, 0x48, 0x20, 0x82, 0x95, 0xf0, + 0xde, 0xa5, 0x1b, 0x85, 0x0a, 0x68, 0x85, 0x4d, + + 0x08, 0x20, 0x94, 0xbd, 0xa4, 0x4d, 0x20, 0xd7, + 0xff, 0x85, 0x27, 0x28, 0x90, 0x1b, 0xa5, 0x27, + + 0xd0, 0xc2, 0x20, 0xd7, 0xff, 0x85, 0x36, 0xaa, + 0xf0, 0x09, 0x20, 0xd7, 0xff, 0x9d, 0xff, 0x05, + + 0xca, 0xd0, 0xf7, 0x20, 0x1e, 0x8c, 0x4c, 0xda, + 0xb9, 0xa5, 0x27, 0xf0, 0xa7, 0x30, 0x0c, 0xa2, + + 0x03, 0x20, 0xd7, 0xff, 0x95, 0x2a, 0xca, 0x10, + 0xf8, 0x30, 0x0e, 0xa2, 0x04, 0x20, 0xd7, 0xff, + + 0x9d, 0x6c, 0x04, 0xca, 0x10, 0xf7, 0x20, 0xb2, + 0xa3, 0x20, 0xb4, 0xb4, 0x4c, 0xda, 0xb9, 0x68, + + 0x68, 0x4c, 0x98, 0x8b, 0x20, 0x97, 0x8a, 0xc9, + 0x23, 0xf0, 0x84, 0xc9, 0x86, 0xf0, 0x03, 0xc6, + + 0x0a, 0x18, 0x66, 0x4d, 0x46, 0x4d, 0xa9, 0xff, + 0x85, 0x4e, 0x20, 0x8a, 0x8e, 0xb0, 0x0a, 0x20, + + 0x8a, 0x8e, 0x90, 0xfb, 0xa2, 0xff, 0x86, 0x4e, + 0x18, 0x08, 0x06, 0x4d, 0x28, 0x66, 0x4d, 0xc9, + + 0x2c, 0xf0, 0xe7, 0xc9, 0x3b, 0xf0, 0xe3, 0xc6, + 0x0a, 0xa5, 0x4d, 0x48, 0xa5, 0x4e, 0x48, 0x20, + + 0x82, 0x95, 0xf0, 0xbb, 0x68, 0x85, 0x4e, 0x68, + 0x85, 0x4d, 0xa5, 0x1b, 0x85, 0x0a, 0x08, 0x24, + + 0x4d, 0x70, 0x06, 0xa5, 0x4e, 0xc9, 0xff, 0xd0, + 0x17, 0x24, 0x4d, 0x10, 0x05, 0xa9, 0x3f, 0x20, + + 0x58, 0xb5, 0x20, 0xfc, 0xbb, 0x84, 0x36, 0x06, + 0x4d, 0x18, 0x66, 0x4d, 0x24, 0x4d, 0x70, 0x1d, + + 0x85, 0x1b, 0xa9, 0x00, 0x85, 0x19, 0xa9, 0x06, + 0x85, 0x1a, 0x20, 0xad, 0xad, 0x20, 0x8c, 0x8a, + + 0xc9, 0x2c, 0xf0, 0x06, 0xc9, 0x0d, 0xd0, 0xf5, + 0xa0, 0xfe, 0xc8, 0x84, 0x4e, 0x28, 0xb0, 0x0c, + + 0x20, 0x94, 0xbd, 0x20, 0x34, 0xac, 0x20, 0xb4, + 0xb4, 0x4c, 0x5a, 0xba, 0xa9, 0x00, 0x85, 0x27, + + 0x20, 0x21, 0x8c, 0x4c, 0x5a, 0xba, 0xa0, 0x00, + 0x84, 0x3d, 0xa4, 0x18, 0x84, 0x3e, 0x20, 0x97, + + 0x8a, 0xc6, 0x0a, 0xc9, 0x3a, 0xf0, 0x10, 0xc9, + 0x0d, 0xf0, 0x0c, 0xc9, 0x8b, 0xf0, 0x08, 0x20, + + 0x9a, 0xb9, 0xa0, 0x01, 0x20, 0x55, 0xbe, 0x20, + 0x57, 0x98, 0xa5, 0x3d, 0x85, 0x1c, 0xa5, 0x3e, + + 0x85, 0x1d, 0x4c, 0x9b, 0x8b, 0x20, 0x97, 0x8a, + 0xc9, 0x2c, 0xf0, 0x03, 0x4c, 0x96, 0x8b, 0x20, + + 0x82, 0x95, 0xf0, 0xf1, 0xb0, 0x0c, 0x20, 0x50, + 0xbb, 0x20, 0x94, 0xbd, 0x20, 0xb1, 0xb4, 0x4c, + + 0x40, 0xbb, 0x20, 0x50, 0xbb, 0x20, 0x94, 0xbd, + 0x20, 0xad, 0xad, 0x85, 0x27, 0x20, 0x1e, 0x8c, + + 0x18, 0xa5, 0x1b, 0x65, 0x19, 0x85, 0x1c, 0xa5, + 0x1a, 0x69, 0x00, 0x85, 0x1d, 0x4c, 0x15, 0xbb, + + 0xa5, 0x1b, 0x85, 0x0a, 0xa5, 0x1c, 0x85, 0x19, + 0xa5, 0x1d, 0x85, 0x1a, 0xa0, 0x00, 0x84, 0x1b, + + 0x20, 0x8c, 0x8a, 0xc9, 0x2c, 0xf0, 0x49, 0xc9, + 0xdc, 0xf0, 0x45, 0xc9, 0x0d, 0xf0, 0x0b, 0x20, + + 0x8c, 0x8a, 0xc9, 0x2c, 0xf0, 0x3a, 0xc9, 0x0d, + 0xd0, 0xf5, 0xa4, 0x1b, 0xb1, 0x19, 0x30, 0x1c, + + 0xc8, 0xc8, 0xb1, 0x19, 0xaa, 0xc8, 0xb1, 0x19, + 0xc9, 0x20, 0xf0, 0xf9, 0xc9, 0xdc, 0xf0, 0x1d, + + 0x8a, 0x18, 0x65, 0x19, 0x85, 0x19, 0x90, 0xe2, + 0xe6, 0x1a, 0xb0, 0xde, 0x00, 0x2a, 0x4f, 0x75, + + 0x74, 0x20, 0x6f, 0x66, 0x20, 0xdc, 0x00, 0x2b, + 0x4e, 0x6f, 0x20, 0xf5, 0x00, 0xc8, 0x84, 0x1b, + + 0x60, 0x20, 0x1d, 0x9b, 0x20, 0x4c, 0x98, 0x20, + 0xee, 0x92, 0xa6, 0x24, 0xf0, 0xe8, 0xa5, 0x2a, + + 0x05, 0x2b, 0x05, 0x2c, 0x05, 0x2d, 0xf0, 0x05, + 0xc6, 0x24, 0x4c, 0x9b, 0x8b, 0xbc, 0xa3, 0x05, + + 0xbd, 0xb7, 0x05, 0x4c, 0xdd, 0xb8, 0x00, 0x2c, + 0x54, 0x6f, 0x6f, 0x20, 0x6d, 0x61, 0x6e, 0x79, + + 0x20, 0xf5, 0x73, 0x00, 0xa6, 0x24, 0xe0, 0x14, + 0xb0, 0xec, 0x20, 0x6d, 0x98, 0xa5, 0x0b, 0x9d, + + 0xa4, 0x05, 0xa5, 0x0c, 0x9d, 0xb8, 0x05, 0xe6, + 0x24, 0x4c, 0xa3, 0x8b, 0xa0, 0x00, 0xa9, 0x06, + + 0xd0, 0x07, 0x20, 0x58, 0xb5, 0xa0, 0x00, 0xa9, + 0x07, 0x84, 0x37, 0x85, 0x38, 0xa9, 0xee, 0x85, + + 0x39, 0xa9, 0x20, 0x85, 0x3a, 0xa0, 0xff, 0x84, + 0x3b, 0xc8, 0xa2, 0x37, 0x98, 0x20, 0xf1, 0xff, + + 0x90, 0x06, 0x4c, 0x38, 0x98, 0x20, 0xe7, 0xff, + 0xa9, 0x00, 0x85, 0x1e, 0x60, 0x20, 0x70, 0x99, + + 0xb0, 0x4e, 0xa5, 0x3d, 0xe9, 0x02, 0x85, 0x37, + 0x85, 0x3d, 0x85, 0x12, 0xa5, 0x3e, 0xe9, 0x00, + + 0x85, 0x38, 0x85, 0x13, 0x85, 0x3e, 0xa0, 0x03, + 0xb1, 0x37, 0x18, 0x65, 0x37, 0x85, 0x37, 0x90, + + 0x02, 0xe6, 0x38, 0xa0, 0x00, 0xb1, 0x37, 0x91, + 0x12, 0xc9, 0x0d, 0xf0, 0x09, 0xc8, 0xd0, 0xf5, + + 0xe6, 0x38, 0xe6, 0x13, 0xd0, 0xef, 0xc8, 0xd0, + 0x04, 0xe6, 0x38, 0xe6, 0x13, 0xb1, 0x37, 0x91, + + 0x12, 0x30, 0x09, 0x20, 0x81, 0xbc, 0x20, 0x81, + 0xbc, 0x4c, 0x5d, 0xbc, 0x20, 0x92, 0xbe, 0x18, + + 0x60, 0xc8, 0xd0, 0x04, 0xe6, 0x13, 0xe6, 0x38, + 0xb1, 0x37, 0x91, 0x12, 0x60, 0x84, 0x3b, 0x20, + + 0x2d, 0xbc, 0xa0, 0x07, 0x84, 0x3c, 0xa0, 0x00, + 0xa9, 0x0d, 0xd1, 0x3b, 0xf0, 0x72, 0xc8, 0xd1, + + 0x3b, 0xd0, 0xfb, 0xc8, 0xc8, 0xc8, 0x84, 0x3f, + 0xe6, 0x3f, 0xa5, 0x12, 0x85, 0x39, 0xa5, 0x13, + + 0x85, 0x3a, 0x20, 0x92, 0xbe, 0x85, 0x37, 0xa5, + 0x13, 0x85, 0x38, 0x88, 0xa5, 0x06, 0xc5, 0x12, + + 0xa5, 0x07, 0xe5, 0x13, 0xb0, 0x10, 0x20, 0x6f, + 0xbe, 0x20, 0x20, 0xbd, 0x00, 0x00, 0x86, 0x20, + + 0x73, 0x70, 0x61, 0x63, 0x65, 0x00, 0xb1, 0x39, + 0x91, 0x37, 0x98, 0xd0, 0x04, 0xc6, 0x3a, 0xc6, + + 0x38, 0x88, 0x98, 0x65, 0x39, 0xa6, 0x3a, 0x90, + 0x01, 0xe8, 0xc5, 0x3d, 0x8a, 0xe5, 0x3e, 0xb0, + + 0xe5, 0x38, 0xa0, 0x01, 0xa5, 0x2b, 0x91, 0x3d, + 0xc8, 0xa5, 0x2a, 0x91, 0x3d, 0xc8, 0xa5, 0x3f, + + 0x91, 0x3d, 0x20, 0x56, 0xbe, 0xa0, 0xff, 0xc8, + 0xb1, 0x3b, 0x91, 0x3d, 0xc9, 0x0d, 0xd0, 0xf7, + + 0x60, 0x20, 0x57, 0x98, 0x20, 0x20, 0xbd, 0xa5, + 0x18, 0x85, 0x0c, 0x86, 0x0b, 0x4c, 0x0b, 0x8b, + + 0xa5, 0x12, 0x85, 0x00, 0x85, 0x02, 0xa5, 0x13, + 0x85, 0x01, 0x85, 0x03, 0x20, 0x3a, 0xbd, 0xa2, + + 0x80, 0xa9, 0x00, 0x9d, 0x7f, 0x04, 0xca, 0xd0, + 0xfa, 0x60, 0xa5, 0x18, 0x85, 0x1d, 0xa5, 0x06, + + 0x85, 0x04, 0xa5, 0x07, 0x85, 0x05, 0xa9, 0x00, + 0x85, 0x24, 0x85, 0x26, 0x85, 0x25, 0x85, 0x1c, + + 0x60, 0xa5, 0x04, 0x38, 0xe9, 0x05, 0x20, 0x2e, + 0xbe, 0xa0, 0x00, 0xa5, 0x30, 0x91, 0x04, 0xc8, + + 0xa5, 0x2e, 0x29, 0x80, 0x85, 0x2e, 0xa5, 0x31, + 0x29, 0x7f, 0x05, 0x2e, 0x91, 0x04, 0xc8, 0xa5, + + 0x32, 0x91, 0x04, 0xc8, 0xa5, 0x33, 0x91, 0x04, + 0xc8, 0xa5, 0x34, 0x91, 0x04, 0x60, 0xa5, 0x04, + + 0x18, 0x85, 0x4b, 0x69, 0x05, 0x85, 0x04, 0xa5, + 0x05, 0x85, 0x4c, 0x69, 0x00, 0x85, 0x05, 0x60, + + 0xf0, 0x20, 0x30, 0xbd, 0xa5, 0x04, 0x38, 0xe9, + 0x04, 0x20, 0x2e, 0xbe, 0xa0, 0x03, 0xa5, 0x2d, + + 0x91, 0x04, 0x88, 0xa5, 0x2c, 0x91, 0x04, 0x88, + 0xa5, 0x2b, 0x91, 0x04, 0x88, 0xa5, 0x2a, 0x91, + + 0x04, 0x60, 0x18, 0xa5, 0x04, 0xe5, 0x36, 0x20, + 0x2e, 0xbe, 0xa4, 0x36, 0xf0, 0x08, 0xb9, 0xff, + + 0x05, 0x91, 0x04, 0x88, 0xd0, 0xf8, 0xa5, 0x36, + 0x91, 0x04, 0x60, 0xa0, 0x00, 0xb1, 0x04, 0x85, + + 0x36, 0xf0, 0x09, 0xa8, 0xb1, 0x04, 0x99, 0xff, + 0x05, 0x88, 0xd0, 0xf8, 0xa0, 0x00, 0xb1, 0x04, + + 0x38, 0x65, 0x04, 0x85, 0x04, 0x90, 0x23, 0xe6, + 0x05, 0x60, 0xa0, 0x03, 0xb1, 0x04, 0x85, 0x2d, + + 0x88, 0xb1, 0x04, 0x85, 0x2c, 0x88, 0xb1, 0x04, + 0x85, 0x2b, 0x88, 0xb1, 0x04, 0x85, 0x2a, 0x18, + + 0xa5, 0x04, 0x69, 0x04, 0x85, 0x04, 0x90, 0x02, + 0xe6, 0x05, 0x60, 0xa2, 0x37, 0xa0, 0x03, 0xb1, + + 0x04, 0x95, 0x03, 0x88, 0xb1, 0x04, 0x95, 0x02, + 0x88, 0xb1, 0x04, 0x95, 0x01, 0x88, 0xb1, 0x04, + + 0x95, 0x00, 0x18, 0xa5, 0x04, 0x69, 0x04, 0x85, + 0x04, 0x90, 0xdf, 0xe6, 0x05, 0x60, 0x85, 0x04, + + 0xb0, 0x02, 0xc6, 0x05, 0xa4, 0x05, 0xc4, 0x03, + 0x90, 0x07, 0xd0, 0x04, 0xc5, 0x02, 0x90, 0x01, + + 0x60, 0x4c, 0xb7, 0x8c, 0xa5, 0x2a, 0x95, 0x00, + 0xa5, 0x2b, 0x95, 0x01, 0xa5, 0x2c, 0x95, 0x02, + + 0xa5, 0x2d, 0x95, 0x03, 0x60, 0x18, 0x98, 0x65, + 0x3d, 0x85, 0x3d, 0x90, 0x02, 0xe6, 0x3e, 0xa0, + + 0x01, 0x60, 0x20, 0xdd, 0xbe, 0xa8, 0xa9, 0xff, + 0x84, 0x3d, 0xa2, 0x37, 0x20, 0xdd, 0xff, 0xa5, + + 0x18, 0x85, 0x13, 0xa0, 0x00, 0x84, 0x12, 0xc8, + 0x88, 0xb1, 0x12, 0xc9, 0x0d, 0xd0, 0x1f, 0xc8, + + 0xb1, 0x12, 0x30, 0x0c, 0xa0, 0x03, 0xb1, 0x12, + 0xf0, 0x14, 0x18, 0x20, 0x93, 0xbe, 0xd0, 0xe8, + + 0xc8, 0x18, 0x98, 0x65, 0x12, 0x85, 0x12, 0x90, + 0x02, 0xe6, 0x13, 0xa0, 0x01, 0x60, 0x20, 0xcf, + + 0xbf, 0x0d, 0x42, 0x61, 0x64, 0x20, 0x70, 0x72, + 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x0d, 0xea, 0x4c, + + 0xf6, 0x8a, 0xa9, 0x00, 0x85, 0x37, 0xa9, 0x06, + 0x85, 0x38, 0xa4, 0x36, 0xa9, 0x0d, 0x99, 0x00, + + 0x06, 0x60, 0x20, 0xd2, 0xbe, 0xa2, 0x00, 0xa0, + 0x06, 0x20, 0xf7, 0xff, 0x4c, 0x9b, 0x8b, 0x4c, + + 0x0e, 0x8c, 0x20, 0x1d, 0x9b, 0xd0, 0xf8, 0x20, + 0xb2, 0xbe, 0x4c, 0x4c, 0x98, 0x20, 0xd2, 0xbe, + + 0x88, 0x84, 0x39, 0xa5, 0x18, 0x85, 0x3a, 0xa9, + 0x82, 0x20, 0xf4, 0xff, 0x86, 0x3b, 0x84, 0x3c, + + 0xa9, 0x00, 0x60, 0x20, 0x6f, 0xbe, 0xa5, 0x12, + 0x85, 0x45, 0xa5, 0x13, 0x85, 0x46, 0xa9, 0x23, + + 0x85, 0x3d, 0xa9, 0x80, 0x85, 0x3e, 0xa5, 0x18, + 0x85, 0x42, 0x20, 0xdd, 0xbe, 0x86, 0x3f, 0x84, + + 0x40, 0x86, 0x43, 0x84, 0x44, 0x86, 0x47, 0x84, + 0x48, 0x85, 0x41, 0xa8, 0xa2, 0x37, 0x20, 0xdd, + + 0xff, 0x4c, 0x9b, 0x8b, 0x20, 0x62, 0xbe, 0x4c, + 0xf3, 0x8a, 0x20, 0x62, 0xbe, 0x4c, 0x14, 0xbd, + + 0x20, 0xa9, 0xbf, 0x48, 0x20, 0x13, 0x98, 0x20, + 0xee, 0x92, 0x68, 0xa8, 0xa2, 0x2a, 0xa9, 0x01, + + 0x20, 0xda, 0xff, 0x4c, 0x9b, 0x8b, 0x38, 0xa9, + 0x00, 0x2a, 0x2a, 0x48, 0x20, 0xb5, 0xbf, 0xa2, + + 0x2a, 0x68, 0x20, 0xda, 0xff, 0xa9, 0x40, 0x60, + 0x20, 0xa9, 0xbf, 0x48, 0x20, 0xae, 0x8a, 0x20, + + 0x49, 0x98, 0x20, 0xee, 0x92, 0x68, 0xa8, 0xa5, + 0x2a, 0x20, 0xd4, 0xff, 0x4c, 0x9b, 0x8b, 0x20, + + 0xb5, 0xbf, 0x20, 0xd7, 0xff, 0x4c, 0xd8, 0xae, + 0xa9, 0x40, 0xd0, 0x06, 0xa9, 0x80, 0xd0, 0x02, + + 0xa9, 0xc0, 0x48, 0x20, 0xec, 0xad, 0xd0, 0x0e, + 0x20, 0xba, 0xbe, 0xa2, 0x00, 0xa0, 0x06, 0x68, + + 0x20, 0xce, 0xff, 0x4c, 0xd8, 0xae, 0x4c, 0x0e, + 0x8c, 0x20, 0xa9, 0xbf, 0x20, 0x52, 0x98, 0xa4, + + 0x2a, 0xa9, 0x00, 0x20, 0xce, 0xff, 0x4c, 0x9b, + 0x8b, 0xa5, 0x0a, 0x85, 0x1b, 0xa5, 0x0b, 0x85, + + 0x19, 0xa5, 0x0c, 0x85, 0x1a, 0x20, 0x8c, 0x8a, + 0xc9, 0x23, 0xd0, 0x07, 0x20, 0xe3, 0x92, 0xa4, + + 0x2a, 0x98, 0x60, 0x00, 0x2d, 0x4d, 0x69, 0x73, + 0x73, 0x69, 0x6e, 0x67, 0x20, 0x23, 0x00, 0x68, + + 0x85, 0x37, 0x68, 0x85, 0x38, 0xa0, 0x00, 0xf0, + 0x03, 0x20, 0xe3, 0xff, 0x20, 0x4b, 0x89, 0x10, + + 0xf8, 0x6c, 0x37, 0x00, 0x20, 0x57, 0x98, 0x20, + 0x25, 0xbc, 0xa0, 0x01, 0xb1, 0xfd, 0xf0, 0x06, + + 0x20, 0x0e, 0xb5, 0xc8, 0xd0, 0xf6, 0x4c, 0x9b, + 0x8b, 0x00, 0x52, 0x6f, 0x67, 0x65, 0x72, 0x00 ] \ No newline at end of file diff --git a/BBCMicro/Sheila.py b/BBCMicro/Sheila.py index 2bd2136..6bfedd3 100644 --- a/BBCMicro/Sheila.py +++ b/BBCMicro/Sheila.py @@ -1,17 +1,16 @@ -BASE = 0xfe00 -TOP = 0xfeff - -class Sheila(object): - - def __init__(self, bbc): - self.bbc = bbc - - def readByte(self, addr): - return 0 - - def writeByte(self, addr, value): - if addr == (0xfe30 - BASE): - self.bbc.setPagedROM(value & 0x0f) - else: - pass - \ No newline at end of file +BASE = 0xfe00 +TOP = 0xfeff + +class Sheila(object): + + def __init__(self, bbc): + self.bbc = bbc + + def readByte(self, addr): + return 0 + + def writeByte(self, addr, value): + if addr == (0xfe30 - BASE): + self.bbc.setPagedROM(value & 0x0f) + else: + pass diff --git a/BBCMicro/System.py b/BBCMicro/System.py index fc550e5..87b03ec 100644 --- a/BBCMicro/System.py +++ b/BBCMicro/System.py @@ -1,29 +1,29 @@ -''' -Created on 16 Oct 2011 - -@author: Chris -''' -import OS -import PagedROM -import Sheila - -class Beeb(object): - def __init__(self, cpu): - self.os = OS.MOS() - self.pagedROM = PagedROM.PagedROM() - self.sheila = Sheila.Sheila(self) - - cpu.memory.map( (OS.BASE, OS.TOP), self.os) - cpu.memory.map( (PagedROM.BASE, PagedROM.TOP), self.pagedROM) - cpu.memory.map( (Sheila.BASE, Sheila.TOP), self.sheila) - - self.cpu = cpu - self.cpu.reset() - self.setPagedROM(0) -# self.cpu.memory.writeByte(0x028c, 15) - - def setPagedROM(self, pagedRom): - self.pagedROM.setPagedROM(pagedRom) - - def tick(self): +''' +Created on 16 Oct 2011 + +@author: Chris +''' +import OS +import PagedROM +import Sheila + +class Beeb(object): + def __init__(self, cpu): + self.os = OS.MOS() + self.pagedROM = PagedROM.PagedROM() + self.sheila = Sheila.Sheila(self) + + cpu.memory.map( (OS.BASE, OS.TOP), self.os) + cpu.memory.map( (PagedROM.BASE, PagedROM.TOP), self.pagedROM) + cpu.memory.map( (Sheila.BASE, Sheila.TOP), self.sheila) + + self.cpu = cpu + self.cpu.reset() + self.setPagedROM(0) +# self.cpu.memory.writeByte(0x028c, 15) + + def setPagedROM(self, pagedRom): + self.pagedROM.setPagedROM(pagedRom) + + def tick(self): self.cpu.dispatch() \ No newline at end of file diff --git a/CPU/AddressDispatcher.py b/CPU/AddressDispatcher.py index db27e86..ac55bc7 100644 --- a/CPU/AddressDispatcher.py +++ b/CPU/AddressDispatcher.py @@ -1,95 +1,94 @@ - -class AddressDispatcher(object): - def __init__(self, memory, registerBank): - self.registers = registerBank - self.memory = memory - - def implicit(self): - return None - - def accumulator(self): - return None - - def immediate(self): - return self.registers.pc + 1 - - def zeroPage(self): - return self.memory.readByte( self.registers.pc + 1) - - def zeroPageX(self): - offset = self.memory.readByte( self.registers.pc + 1) - addr = offset + self.registers.x - return addr & 0xff - - def zeroPageY(self): - offset = self.memory.readByte( self.registers.pc + 1) - addr = offset + self.registers.y - return addr & 0xff - - def relative(self): - offset = self.memory.readSignedByte( self.registers.pc + 1) - return offset + self.registers.nextPC - - def absolute(self): - return self.memory.readWord(self.registers.pc + 1) - - def absoluteX(self): - offset = self.memory.readWord(self.registers.pc + 1) - return self.registers.x + offset - - def absoluteY(self): - offset = self.memory.readWord(self.registers.pc + 1) - return self.registers.y + offset - - def indirect(self): - addr = self.memory.readWord(self.registers.pc + 1) - return self.memory.readWord(addr) - - def indirectX(self): - addr = self.memory.readByte(self.registers.pc + 1) + self.registers.x - addr = addr & 0xff - return self.memory.readWord(addr) - - def indirectY(self): - addr = self.memory.readByte(self.registers.pc + 1) - return self.memory.readWord(addr) + self.registers.y - - def implicitRead(self): - return None - - def accumulatorRead(self): - return self.registers.a - - def immediateRead(self): - return self.memory.readByte(self.immediate()) - - def zeroPageRead(self): - return self.memory.readByte(self.zeroPage()) - - def zeroPageXRead(self): - return self.memory.readByte(self.zeroPageX()) - - def zeroPageYRead(self): - return self.memory.readByte(self.zeroPageY()) - - def relativeRead(self): - return self.memory.readByte(self.relative()) # hack hack hack - - def absoluteRead(self): - return self.memory.readByte(self.absolute()) - - def absoluteXRead(self): - return self.memory.readByte(self.absoluteX()) - - def absoluteYRead(self): - return self.memory.readByte(self.absoluteY()) - - def indirectRead(self): - return self.memory.readByte(self.indirect()) - - def indirectXRead(self): - return self.memory.readByte(self.indirectX()) - - def indirectYRead(self): - return self.memory.readByte(self.indirectY()) - \ No newline at end of file + +class AddressDispatcher(object): + def __init__(self, memory, registerBank): + self.registers = registerBank + self.memory = memory + + def implicit(self): + return None + + def accumulator(self): + return None + + def immediate(self): + return self.registers.pc + 1 + + def zeroPage(self): + return self.memory.readByte( self.registers.pc + 1) + + def zeroPageX(self): + offset = self.memory.readByte( self.registers.pc + 1) + addr = offset + self.registers.x + return addr & 0xff + + def zeroPageY(self): + offset = self.memory.readByte( self.registers.pc + 1) + addr = offset + self.registers.y + return addr & 0xff + + def relative(self): + offset = self.memory.readSignedByte( self.registers.pc + 1) + return offset + self.registers.nextPC + + def absolute(self): + return self.memory.readWord(self.registers.pc + 1) + + def absoluteX(self): + offset = self.memory.readWord(self.registers.pc + 1) + return self.registers.x + offset + + def absoluteY(self): + offset = self.memory.readWord(self.registers.pc + 1) + return self.registers.y + offset + + def indirect(self): + addr = self.memory.readWord(self.registers.pc + 1) + return self.memory.readWord(addr) + + def indirectX(self): + addr = self.memory.readByte(self.registers.pc + 1) + self.registers.x + addr = addr & 0xff + return self.memory.readWord(addr) + + def indirectY(self): + addr = self.memory.readByte(self.registers.pc + 1) + return self.memory.readWord(addr) + self.registers.y + + def implicitRead(self): + return None + + def accumulatorRead(self): + return self.registers.a + + def immediateRead(self): + return self.memory.readByte(self.immediate()) + + def zeroPageRead(self): + return self.memory.readByte(self.zeroPage()) + + def zeroPageXRead(self): + return self.memory.readByte(self.zeroPageX()) + + def zeroPageYRead(self): + return self.memory.readByte(self.zeroPageY()) + + def relativeRead(self): + return self.memory.readByte(self.relative()) # hack hack hack + + def absoluteRead(self): + return self.memory.readByte(self.absolute()) + + def absoluteXRead(self): + return self.memory.readByte(self.absoluteX()) + + def absoluteYRead(self): + return self.memory.readByte(self.absoluteY()) + + def indirectRead(self): + return self.memory.readByte(self.indirect()) + + def indirectXRead(self): + return self.memory.readByte(self.indirectX()) + + def indirectYRead(self): + return self.memory.readByte(self.indirectY()) diff --git a/CPU/Dispatch.py b/CPU/Dispatch.py index 355f678..2a4abca 100644 --- a/CPU/Dispatch.py +++ b/CPU/Dispatch.py @@ -1,138 +1,138 @@ -''' -Created on 12 Oct 2011 - -@author: chris.whitworth -''' - -class Dispatcher: - def __init__(self, decoder, addressDispatcher, executionDispatcher, writebackDispatcher, memory, registers): - self.decoder = decoder - self.memory = memory - self.registers = registers - self.addressTable = { "imp": addressDispatcher.implicit, - "acc": addressDispatcher.accumulator, - "imm": addressDispatcher.immediate, - "zp" : addressDispatcher.zeroPage, - "zpx": addressDispatcher.zeroPageX, - "zpy": addressDispatcher.zeroPageY, - "rel": addressDispatcher.relative, - "abs": addressDispatcher.absolute, - "abx": addressDispatcher.absoluteX, - "aby": addressDispatcher.absoluteY, - "ind": addressDispatcher.indirect, - "inx": addressDispatcher.indirectX, - "iny": addressDispatcher.indirectY - } - self.dataTable = { "imp": addressDispatcher.implicitRead, - "acc": addressDispatcher.accumulatorRead, - "imm": addressDispatcher.immediateRead, - "zp" : addressDispatcher.zeroPageRead, - "zpx": addressDispatcher.zeroPageXRead, - "zpy": addressDispatcher.zeroPageYRead, - "rel": addressDispatcher.relativeRead, - "abs": addressDispatcher.absoluteRead, - "abx": addressDispatcher.absoluteXRead, - "aby": addressDispatcher.absoluteYRead, - "ind": addressDispatcher.indirectRead, - "inx": addressDispatcher.indirectXRead, - "iny": addressDispatcher.indirectYRead - } - - self.executionTable = { "ADC" : executionDispatcher.ADC, - "AND" : executionDispatcher.AND, - "ASL" : executionDispatcher.ASL, - "BCC" : executionDispatcher.BCC, - "BCS" : executionDispatcher.BCS, - "BEQ" : executionDispatcher.BEQ, - "BIT" : executionDispatcher.BIT, - "BMI" : executionDispatcher.BMI, - "BNE" : executionDispatcher.BNE, - "BPL" : executionDispatcher.BPL, - "BRK" : executionDispatcher.BRK, - "BVC" : executionDispatcher.BVC, - "BVS" : executionDispatcher.BVS, - "CLC" : executionDispatcher.CLC, - "CLD" : executionDispatcher.CLD, - "CLI" : executionDispatcher.CLI, - "CLV" : executionDispatcher.CLV, - "CMP" : executionDispatcher.CMP, - "CPX" : executionDispatcher.CPX, - "CPY" : executionDispatcher.CPY, - "DEC" : executionDispatcher.DEC, - "DEX" : executionDispatcher.DEX, - "DEY" : executionDispatcher.DEY, - "EOR" : executionDispatcher.EOR, - "INC" : executionDispatcher.INC, - "INX" : executionDispatcher.INX, - "INY" : executionDispatcher.INY, - "JMP" : executionDispatcher.JMP, - "JSR" : executionDispatcher.JSR, - "LDA" : executionDispatcher.LDA, - "LDX" : executionDispatcher.LDX, - "LDY" : executionDispatcher.LDY, - "LSR" : executionDispatcher.LSR, - "NOP" : executionDispatcher.NOP, - "ORA" : executionDispatcher.ORA, - "PHA" : executionDispatcher.PHA, - "PHP" : executionDispatcher.PHP, - "PLA" : executionDispatcher.PLA, - "PLP" : executionDispatcher.PLP, - "ROL" : executionDispatcher.ROL, - "ROR" : executionDispatcher.ROR, - "RTI" : executionDispatcher.RTI, - "RTS" : executionDispatcher.RTS, - "SBC" : executionDispatcher.SBC, - "SEC" : executionDispatcher.SEC, - "SED" : executionDispatcher.SED, - "SEI" : executionDispatcher.SEI, - "STA" : executionDispatcher.STA, - "STX" : executionDispatcher.STX, - "STY" : executionDispatcher.STY, - "TAX" : executionDispatcher.TAX, - "TAY" : executionDispatcher.TAY, - "TSX" : executionDispatcher.TSX, - "TXA" : executionDispatcher.TXA, - "TXS" : executionDispatcher.TXS, - "TYA" : executionDispatcher.TYA, - "UNDEFINED" : executionDispatcher.UNDEFINED - } - self.writebackTable = { "A" : writebackDispatcher.A, - "X" : writebackDispatcher.X, - "Y" : writebackDispatcher.Y, - "M" : writebackDispatcher.memory, - "PC" : writebackDispatcher.PC, - "SP" : writebackDispatcher.SP, - "PS" : writebackDispatcher.PS, - "NW" : writebackDispatcher.NW - } - - def dataDecode(self, opcode): - addressingMode = self.decoder.addressingMode(opcode) - return self.dataTable[addressingMode]() - - def addressDecode(self, opcode): - addressingMode = self.decoder.addressingMode(opcode) - return self.addressTable[addressingMode]() - - def dispatch(self): - #Decode - opcode = self.memory.readByte(self.registers.pc) - instruction = self.decoder.instruction(opcode) - writeback = self.decoder.writeback(opcode) - self.registers.nextPC = self.registers.pc + self.decoder.instructionLength(opcode) - - #execute - data = self.dataDecode(opcode) - address = self.addressDecode(opcode) - result = self.executionTable[instruction](data, address) - - if result != None: - self.writebackTable[writeback](result, address) - - self.registers.pc = self.registers.nextPC - - return result - - def reset(self): - self.registers.reset() +''' +Created on 12 Oct 2011 + +@author: chris.whitworth +''' + +class Dispatcher: + def __init__(self, decoder, addressDispatcher, executionDispatcher, writebackDispatcher, memory, registers): + self.decoder = decoder + self.memory = memory + self.registers = registers + self.addressTable = { "imp": addressDispatcher.implicit, + "acc": addressDispatcher.accumulator, + "imm": addressDispatcher.immediate, + "zp" : addressDispatcher.zeroPage, + "zpx": addressDispatcher.zeroPageX, + "zpy": addressDispatcher.zeroPageY, + "rel": addressDispatcher.relative, + "abs": addressDispatcher.absolute, + "abx": addressDispatcher.absoluteX, + "aby": addressDispatcher.absoluteY, + "ind": addressDispatcher.indirect, + "inx": addressDispatcher.indirectX, + "iny": addressDispatcher.indirectY + } + self.dataTable = { "imp": addressDispatcher.implicitRead, + "acc": addressDispatcher.accumulatorRead, + "imm": addressDispatcher.immediateRead, + "zp" : addressDispatcher.zeroPageRead, + "zpx": addressDispatcher.zeroPageXRead, + "zpy": addressDispatcher.zeroPageYRead, + "rel": addressDispatcher.relativeRead, + "abs": addressDispatcher.absoluteRead, + "abx": addressDispatcher.absoluteXRead, + "aby": addressDispatcher.absoluteYRead, + "ind": addressDispatcher.indirectRead, + "inx": addressDispatcher.indirectXRead, + "iny": addressDispatcher.indirectYRead + } + + self.executionTable = { "ADC" : executionDispatcher.ADC, + "AND" : executionDispatcher.AND, + "ASL" : executionDispatcher.ASL, + "BCC" : executionDispatcher.BCC, + "BCS" : executionDispatcher.BCS, + "BEQ" : executionDispatcher.BEQ, + "BIT" : executionDispatcher.BIT, + "BMI" : executionDispatcher.BMI, + "BNE" : executionDispatcher.BNE, + "BPL" : executionDispatcher.BPL, + "BRK" : executionDispatcher.BRK, + "BVC" : executionDispatcher.BVC, + "BVS" : executionDispatcher.BVS, + "CLC" : executionDispatcher.CLC, + "CLD" : executionDispatcher.CLD, + "CLI" : executionDispatcher.CLI, + "CLV" : executionDispatcher.CLV, + "CMP" : executionDispatcher.CMP, + "CPX" : executionDispatcher.CPX, + "CPY" : executionDispatcher.CPY, + "DEC" : executionDispatcher.DEC, + "DEX" : executionDispatcher.DEX, + "DEY" : executionDispatcher.DEY, + "EOR" : executionDispatcher.EOR, + "INC" : executionDispatcher.INC, + "INX" : executionDispatcher.INX, + "INY" : executionDispatcher.INY, + "JMP" : executionDispatcher.JMP, + "JSR" : executionDispatcher.JSR, + "LDA" : executionDispatcher.LDA, + "LDX" : executionDispatcher.LDX, + "LDY" : executionDispatcher.LDY, + "LSR" : executionDispatcher.LSR, + "NOP" : executionDispatcher.NOP, + "ORA" : executionDispatcher.ORA, + "PHA" : executionDispatcher.PHA, + "PHP" : executionDispatcher.PHP, + "PLA" : executionDispatcher.PLA, + "PLP" : executionDispatcher.PLP, + "ROL" : executionDispatcher.ROL, + "ROR" : executionDispatcher.ROR, + "RTI" : executionDispatcher.RTI, + "RTS" : executionDispatcher.RTS, + "SBC" : executionDispatcher.SBC, + "SEC" : executionDispatcher.SEC, + "SED" : executionDispatcher.SED, + "SEI" : executionDispatcher.SEI, + "STA" : executionDispatcher.STA, + "STX" : executionDispatcher.STX, + "STY" : executionDispatcher.STY, + "TAX" : executionDispatcher.TAX, + "TAY" : executionDispatcher.TAY, + "TSX" : executionDispatcher.TSX, + "TXA" : executionDispatcher.TXA, + "TXS" : executionDispatcher.TXS, + "TYA" : executionDispatcher.TYA, + "UNDEFINED" : executionDispatcher.UNDEFINED + } + self.writebackTable = { "A" : writebackDispatcher.A, + "X" : writebackDispatcher.X, + "Y" : writebackDispatcher.Y, + "M" : writebackDispatcher.memory, + "PC" : writebackDispatcher.PC, + "SP" : writebackDispatcher.SP, + "PS" : writebackDispatcher.PS, + "NW" : writebackDispatcher.NW + } + + def dataDecode(self, opcode): + addressingMode = self.decoder.addressingMode(opcode) + return self.dataTable[addressingMode]() + + def addressDecode(self, opcode): + addressingMode = self.decoder.addressingMode(opcode) + return self.addressTable[addressingMode]() + + def dispatch(self): + #Decode + opcode = self.memory.readByte(self.registers.pc) + instruction = self.decoder.instruction(opcode) + writeback = self.decoder.writeback(opcode) + self.registers.nextPC = self.registers.pc + self.decoder.instructionLength(opcode) + + #execute + data = self.dataDecode(opcode) + address = self.addressDecode(opcode) + result = self.executionTable[instruction](data, address) + + if result != None: + self.writebackTable[writeback](result, address) + + self.registers.pc = self.registers.nextPC + + return result + + def reset(self): + self.registers.reset() self.registers.pc = self.memory.readWord(0xfffc) \ No newline at end of file diff --git a/CPU/ExecutionUnit.py b/CPU/ExecutionUnit.py index 8cebf7e..579cab8 100644 --- a/CPU/ExecutionUnit.py +++ b/CPU/ExecutionUnit.py @@ -1,354 +1,354 @@ -''' -Created on 13 Oct 2011 - -@author: chris.whitworth -''' - -class StackOverflowException(BaseException): - pass -class StackUnderflowException(BaseException): - pass - -class ExecutionDispatcher(object): - class NotImplementedException(BaseException): - def __init__(self): - self.instr = "" - - def __repr__(self): - "%s is not implemented" - - def __init__(self, memory, registers): - self.memory = memory - self.registers = registers - - def pushByte(self, value): - self.memory.writeByte(self.registers.sp + 0x100, value) - self.registers.sp -= 1 - if self.registers.sp < 0x00: - raise StackOverflowException() - - def pullByte(self): - self.registers.sp += 1 - if self.registers.sp > 0xff: - raise StackUnderflowException() - - return self.memory.readByte(self.registers.sp + 0x100) - - def pushWord(self, value): - self.pushByte( value >> 8) - self.pushByte( value & 0xff ) - - def pullWord(self): - lw = self.pullByte() - hw = self.pullByte() << 8 - return lw + hw - - def doCompare(self, mem, reg): - result = reg - mem - self.registers.negative = (result < 0 or result > 127) - self.registers.zero = (result == 0) - self.registers.carry = (result >= 0) - - def ADC(self, data, address): - result = self.registers.a + data + (1 if self.registers.carry else 0) - self.registers.negative = (result & 0x80) != 0 - self.registers.carry = (result > 255) - self.registers.zero = (result == 0) - return result & 0xff - - def AND(self, data, address): - result = self.registers.a & data - self.registers.zero = (result == 0) - self.registers.negative = (result & 0x80) != 0 - return result - - def ASL(self, data, address): - result = data << 1 - self.registers.carry = (result > 255) - self.registers.zero = (result == 0) - self.registers.negative = (result & 0x80) != 0 - return result & 0xff - - def BCC(self, data, address): - if not self.registers.carry: - return address - else: - return None - - def BCS(self, data, address): - if self.registers.carry: - return address - else: - return None - - def BEQ(self, data, address): - if self.registers.zero: - return address - else: - return None - - def BIT(self, data, address): - result = self.registers.a & data - self.registers.negative = (data & 0x80) != 0 - self.registers.overflow = (data & 0x40) != 0 - self.registers.zero = (result == 0) - return None - - def BMI(self, data, address): - if self.registers.negative: - return address - else: - return None - - def BNE(self, data, address): - if not self.registers.zero: - return address - else: - return None - - def BPL(self, data, address): - if not self.registers.negative: - return address - else: - return None - - def BRK(self, data, address): - self.registers.brk = True - self.pushWord(self.registers.pc + 2) - self.pushByte(self.registers.ps()) - return self.memory.readWord(0xfffe) - - def BVC(self, data, address): - if not self.registers.overflow: - return address - else: - return None - - def BVS(self, data, address): - if self.registers.overflow: - return address - else: - return None - - def CLC(self, data, address): - self.registers.carry = False - return None - - def CLD(self, data, address): - self.registers.dec = False - return None - - def CLI(self, data, address): - self.registers.int = False - return None - - def CLV(self, data, address): - self.registers.overflow = False - return None - - def CMP(self, data, address): - self.doCompare(data, self.registers.a) - return None - - def CPX(self, data, address): - self.doCompare(data, self.registers.x) - return None - - def CPY(self, data, address): - self.doCompare(data, self.registers.y) - return None - - def DEC(self, data, address): - result = data - 1 - self.registers.zero = (result == 0) - self.registers.negative = (result & 0x80) != 0 - return result & 0xff - - def DEX(self, data, address): - result = self.registers.x - 1 - self.registers.zero = (result == 0) - self.registers.negative = (result & 0x80) != 0 - return result & 0xff - - def DEY(self, data, address): - result = self.registers.y - 1 - self.registers.zero = (result == 0) - self.registers.negative = (result & 0x80) != 0 - return result & 0xff - - def EOR(self, data, address): - result = self.registers.a ^ data - self.registers.zero = (result == 0) - self.registers.negative = (result & 0x80) != 0 - return result - - def INC(self, data, address): - result = (data + 1) & 0xff - self.registers.zero = (result == 0) - self.registers.negative = (result & 0x80) != 0 - return result - - def INX(self, data, address): - result = (self.registers.x + 1) & 0xff - self.registers.zero = (result == 0) - self.registers.negative = (result & 0x80) != 0 - return result - - def INY(self, data, address): - result = (self.registers.y + 1) & 0xff - self.registers.zero = (result == 0) - self.registers.negative = (result & 0x80) != 0 - return result - - def JMP(self, data, address): - return address - - def JSR(self, data, address): - self.pushWord(self.registers.pc + 2) - return address - - def LDA(self, data, address): - self.registers.zero = (data == 0) - self.registers.negative = (data & 0x80) != 0 - return data - - def LDX(self, data, address): - self.registers.zero = (data == 0) - self.registers.negative = (data & 0x80) != 0 - return data - - def LDY(self, data, address): - self.registers.zero = (data == 0) - self.registers.negative = (data & 0x80) != 0 - return data - - def LSR(self, data, address): - self.registers.carry = (data & 0x01) != 0 - result = data >> 1 - self.registers.zero = (result == 0) - self.registers.negative = (result & 0x80) != 0 - return result & 0xff - - def NOP(self, data, address): - pass - - def ORA(self, data, address): - result = data | self.registers.a - self.registers.zero = (result == 0) - self.registers.negative = (result & 0x80) != 0 - return result - - def PHA(self, data, address): - self.pushByte(self.registers.a) - return None - - def PHP(self, data, address): - self.pushByte(self.registers.ps()) - return None - - def PLA(self, data, address): - result = self.pullByte() - self.registers.zero = (result == 0) - self.registers.negative = (result & 0x80) != 0 - return result - - def PLP(self, data, address): - result = self.pullByte() - self.registers.setPS(result) - return None - - def ROL(self, data, address): - oldCarry = 0x01 if self.registers.carry else 0x00 - self.registers.carry = (data & 0x80) != 0 - result = (data << 1) & 0xff - result = result | oldCarry - self.registers.zero = (result == 0) - self.registers.negative = (result & 0x80) != 0 - return result - - def ROR(self, data, address): - oldCarry = 0x80 if self.registers.carry else 0x00 - self.registers.carry = (data & 0x01) != 0 - result = (data >> 1) | (oldCarry) - self.registers.zero = (result == 0) - self.registers.negative = (result & 0x80) != 0 - return result - - def RTI(self, data, address): - self.registers.setPS(self.pullByte()) - self.registers.brk = False - return self.pullWord() - - - def RTS(self, data, address): - location = self.pullWord() - return location + 1 - - def SBC(self, data, address): - result = (~data) & 0xff - result += self.registers.a + (1 if self.registers.carry else 0) - self.registers.zero = (result == 0) - self.registers.negative = (result & 0x80) != 0 - self.registers.carry = (result > 255) - return result & 0xff - - def SEC(self, data, address): - self.registers.carry = True - return None - - def SED(self, data, address): - self.registers.dec = True - return None - - def SEI(self, data, address): - self.registers.int = True - return None - - def STA(self, data, address): - return self.registers.a - - def STX(self, data, address): - return self.registers.x - - def STY(self, data, address): - return self.registers.y - - def TAX(self, data, address): - result = self.registers.a - self.registers.zero = (result == 0) - self.registers.negative = (result & 0x80) != 0 - return result - - def TAY(self, data, address): - result = self.registers.a - self.registers.zero = (result == 0) - self.registers.negative = (result & 0x80) != 0 - return result - - def TSX(self, data, address): - result = self.registers.sp - self.registers.zero = (result == 0) - self.registers.negative = (result & 0x80) != 0 - return result - - def TXA(self, data, address): - result = self.registers.x - self.registers.zero = (result == 0) - self.registers.negative = (result & 0x80) != 0 - return result - - def TXS(self, data, address): - result = self.registers.x - self.registers.zero = (result == 0) - self.registers.negative = (result & 0x80) != 0 - return result - - def TYA(self, data, address): - result = self.registers.y - self.registers.zero = (result == 0) - self.registers.negative = (result & 0x80) != 0 - return result - - def UNDEFINED(self, data, address): - pass -# raise self.NotImplementedException() +''' +Created on 13 Oct 2011 + +@author: chris.whitworth +''' + +class StackOverflowException(BaseException): + pass +class StackUnderflowException(BaseException): + pass + +class ExecutionDispatcher(object): + class NotImplementedException(BaseException): + def __init__(self): + self.instr = "" + + def __repr__(self): + "%s is not implemented" + + def __init__(self, memory, registers): + self.memory = memory + self.registers = registers + + def pushByte(self, value): + self.memory.writeByte(self.registers.sp + 0x100, value) + self.registers.sp -= 1 + if self.registers.sp < 0x00: + raise StackOverflowException() + + def pullByte(self): + self.registers.sp += 1 + if self.registers.sp > 0xff: + raise StackUnderflowException() + + return self.memory.readByte(self.registers.sp + 0x100) + + def pushWord(self, value): + self.pushByte( value >> 8) + self.pushByte( value & 0xff ) + + def pullWord(self): + lw = self.pullByte() + hw = self.pullByte() << 8 + return lw + hw + + def doCompare(self, mem, reg): + result = reg - mem + self.registers.negative = (result < 0 or result > 127) + self.registers.zero = (result == 0) + self.registers.carry = (result >= 0) + + def ADC(self, data, address): + result = self.registers.a + data + (1 if self.registers.carry else 0) + self.registers.negative = (result & 0x80) != 0 + self.registers.carry = (result > 255) + self.registers.zero = (result == 0) + return result & 0xff + + def AND(self, data, address): + result = self.registers.a & data + self.registers.zero = (result == 0) + self.registers.negative = (result & 0x80) != 0 + return result + + def ASL(self, data, address): + result = data << 1 + self.registers.carry = (result > 255) + self.registers.zero = (result == 0) + self.registers.negative = (result & 0x80) != 0 + return result & 0xff + + def BCC(self, data, address): + if not self.registers.carry: + return address + else: + return None + + def BCS(self, data, address): + if self.registers.carry: + return address + else: + return None + + def BEQ(self, data, address): + if self.registers.zero: + return address + else: + return None + + def BIT(self, data, address): + result = self.registers.a & data + self.registers.negative = (data & 0x80) != 0 + self.registers.overflow = (data & 0x40) != 0 + self.registers.zero = (result == 0) + return None + + def BMI(self, data, address): + if self.registers.negative: + return address + else: + return None + + def BNE(self, data, address): + if not self.registers.zero: + return address + else: + return None + + def BPL(self, data, address): + if not self.registers.negative: + return address + else: + return None + + def BRK(self, data, address): + self.registers.brk = True + self.pushWord(self.registers.pc + 2) + self.pushByte(self.registers.ps()) + return self.memory.readWord(0xfffe) + + def BVC(self, data, address): + if not self.registers.overflow: + return address + else: + return None + + def BVS(self, data, address): + if self.registers.overflow: + return address + else: + return None + + def CLC(self, data, address): + self.registers.carry = False + return None + + def CLD(self, data, address): + self.registers.dec = False + return None + + def CLI(self, data, address): + self.registers.int = False + return None + + def CLV(self, data, address): + self.registers.overflow = False + return None + + def CMP(self, data, address): + self.doCompare(data, self.registers.a) + return None + + def CPX(self, data, address): + self.doCompare(data, self.registers.x) + return None + + def CPY(self, data, address): + self.doCompare(data, self.registers.y) + return None + + def DEC(self, data, address): + result = data - 1 + self.registers.zero = (result == 0) + self.registers.negative = (result & 0x80) != 0 + return result & 0xff + + def DEX(self, data, address): + result = self.registers.x - 1 + self.registers.zero = (result == 0) + self.registers.negative = (result & 0x80) != 0 + return result & 0xff + + def DEY(self, data, address): + result = self.registers.y - 1 + self.registers.zero = (result == 0) + self.registers.negative = (result & 0x80) != 0 + return result & 0xff + + def EOR(self, data, address): + result = self.registers.a ^ data + self.registers.zero = (result == 0) + self.registers.negative = (result & 0x80) != 0 + return result + + def INC(self, data, address): + result = (data + 1) & 0xff + self.registers.zero = (result == 0) + self.registers.negative = (result & 0x80) != 0 + return result + + def INX(self, data, address): + result = (self.registers.x + 1) & 0xff + self.registers.zero = (result == 0) + self.registers.negative = (result & 0x80) != 0 + return result + + def INY(self, data, address): + result = (self.registers.y + 1) & 0xff + self.registers.zero = (result == 0) + self.registers.negative = (result & 0x80) != 0 + return result + + def JMP(self, data, address): + return address + + def JSR(self, data, address): + self.pushWord(self.registers.pc + 2) + return address + + def LDA(self, data, address): + self.registers.zero = (data == 0) + self.registers.negative = (data & 0x80) != 0 + return data + + def LDX(self, data, address): + self.registers.zero = (data == 0) + self.registers.negative = (data & 0x80) != 0 + return data + + def LDY(self, data, address): + self.registers.zero = (data == 0) + self.registers.negative = (data & 0x80) != 0 + return data + + def LSR(self, data, address): + self.registers.carry = (data & 0x01) != 0 + result = data >> 1 + self.registers.zero = (result == 0) + self.registers.negative = (result & 0x80) != 0 + return result & 0xff + + def NOP(self, data, address): + pass + + def ORA(self, data, address): + result = data | self.registers.a + self.registers.zero = (result == 0) + self.registers.negative = (result & 0x80) != 0 + return result + + def PHA(self, data, address): + self.pushByte(self.registers.a) + return None + + def PHP(self, data, address): + self.pushByte(self.registers.ps()) + return None + + def PLA(self, data, address): + result = self.pullByte() + self.registers.zero = (result == 0) + self.registers.negative = (result & 0x80) != 0 + return result + + def PLP(self, data, address): + result = self.pullByte() + self.registers.setPS(result) + return None + + def ROL(self, data, address): + oldCarry = 0x01 if self.registers.carry else 0x00 + self.registers.carry = (data & 0x80) != 0 + result = (data << 1) & 0xff + result = result | oldCarry + self.registers.zero = (result == 0) + self.registers.negative = (result & 0x80) != 0 + return result + + def ROR(self, data, address): + oldCarry = 0x80 if self.registers.carry else 0x00 + self.registers.carry = (data & 0x01) != 0 + result = (data >> 1) | (oldCarry) + self.registers.zero = (result == 0) + self.registers.negative = (result & 0x80) != 0 + return result + + def RTI(self, data, address): + self.registers.setPS(self.pullByte()) + self.registers.brk = False + return self.pullWord() + + + def RTS(self, data, address): + location = self.pullWord() + return location + 1 + + def SBC(self, data, address): + result = (~data) & 0xff + result += self.registers.a + (1 if self.registers.carry else 0) + self.registers.zero = (result == 0) + self.registers.negative = (result & 0x80) != 0 + self.registers.carry = (result > 255) + return result & 0xff + + def SEC(self, data, address): + self.registers.carry = True + return None + + def SED(self, data, address): + self.registers.dec = True + return None + + def SEI(self, data, address): + self.registers.int = True + return None + + def STA(self, data, address): + return self.registers.a + + def STX(self, data, address): + return self.registers.x + + def STY(self, data, address): + return self.registers.y + + def TAX(self, data, address): + result = self.registers.a + self.registers.zero = (result == 0) + self.registers.negative = (result & 0x80) != 0 + return result + + def TAY(self, data, address): + result = self.registers.a + self.registers.zero = (result == 0) + self.registers.negative = (result & 0x80) != 0 + return result + + def TSX(self, data, address): + result = self.registers.sp + self.registers.zero = (result == 0) + self.registers.negative = (result & 0x80) != 0 + return result + + def TXA(self, data, address): + result = self.registers.x + self.registers.zero = (result == 0) + self.registers.negative = (result & 0x80) != 0 + return result + + def TXS(self, data, address): + result = self.registers.x + self.registers.zero = (result == 0) + self.registers.negative = (result & 0x80) != 0 + return result + + def TYA(self, data, address): + result = self.registers.y + self.registers.zero = (result == 0) + self.registers.negative = (result & 0x80) != 0 + return result + + def UNDEFINED(self, data, address): + pass +# raise self.NotImplementedException() diff --git a/CPU/InstructionDecoder.py b/CPU/InstructionDecoder.py index bfbcb47..f06ef93 100644 --- a/CPU/InstructionDecoder.py +++ b/CPU/InstructionDecoder.py @@ -1,32 +1,32 @@ -class Decoder(object): - def __init__(self, decodeFilename): - decodeFile = open(decodeFilename) - self.loadDecodeTable(decodeFile) - - def loadDecodeTable(self, decodeFile): - self.decodeTable = {} - for entry in decodeFile: - (opcode, instr, addr, wb, byteLen, time) = entry.split(",") - try: - if instr != "": - self.decodeTable[int(opcode,16)] = (instr, addr, wb, int(byteLen), int(time)) - else: - self.decodeTable[int(opcode,16)] = ("UNDEFINED", "imp", "NW", 1, 1) - except ValueError: - pass - - def instruction(self, opcode): - return self.decodeTable[opcode][0] - - def addressingMode(self, opcode): - return self.decodeTable[opcode][1] - - def writeback(self, opcode): - return self.decodeTable[opcode][2] - - def instructionLength(self, opcode): - return self.decodeTable[opcode][3] - - def clockCycles(self, opcode): - ''' This will, in general, be wrong ''' - return self.decodeTable[opcode][4] \ No newline at end of file +class Decoder(object): + def __init__(self, decodeFilename): + decodeFile = open(decodeFilename) + self.loadDecodeTable(decodeFile) + + def loadDecodeTable(self, decodeFile): + self.decodeTable = {} + for entry in decodeFile: + (opcode, instr, addr, wb, byteLen, time) = entry.split(",") + try: + if instr != "": + self.decodeTable[int(opcode,16)] = (instr, addr, wb, int(byteLen), int(time)) + else: + self.decodeTable[int(opcode,16)] = ("UNDEFINED", "imp", "NW", 1, 1) + except ValueError: + pass + + def instruction(self, opcode): + return self.decodeTable[opcode][0] + + def addressingMode(self, opcode): + return self.decodeTable[opcode][1] + + def writeback(self, opcode): + return self.decodeTable[opcode][2] + + def instructionLength(self, opcode): + return self.decodeTable[opcode][3] + + def clockCycles(self, opcode): + ''' This will, in general, be wrong ''' + return self.decodeTable[opcode][4] \ No newline at end of file diff --git a/CPU/Memory.py b/CPU/Memory.py index e62cb00..5bb2d4d 100644 --- a/CPU/Memory.py +++ b/CPU/Memory.py @@ -1,94 +1,94 @@ -''' -Created on 12 Oct 2011 - -@author: chris.whitworth -''' -from struct import unpack - -class InvalidAddressException(Exception): - def __init__(self, address): - self.address = address - - def __repr__(self): - return "Invalid address: %s" % hex(self.address) - -class ValueOutOfRange(Exception): - def __init__(self, value): - self.value = value - - def __repr__(self): - return "Value out of range: %s" % hex(self.value) - -class Memory(object): - class Map(object): - def __init__(self, range, callback): - self.range = range - self.callback = callback - - def base(self): - return self.range[0] - - def end(self): - return self.range[1] - - def isInMap(self, address): - return True if address >= self.base() and address < self.end() else False - - MEMORYSIZE = 64 * 1024 - def __init__(self): - self.memory = bytearray(self.MEMORYSIZE) - self.protection = bytearray(self.MEMORYSIZE) - self.maps = [] - - def map(self, range, callback): - self.maps.append( self.Map(range, callback) ) - - def unmap(self, range): - raise BaseException("Cannae do this") - - def getMapFor(self, address): - maps = [ map for map in self.maps if map.isInMap(address) ] - if len(maps) != 0: - return maps[-1] - else: - return None - - def readByte(self, address): - # TODO - add memory mapping - if address < 0 or address > 0xffff: - raise InvalidAddressException(address) - - map = self.getMapFor(address) - - if map != None: - base = map.base() - mappedDevice = map.callback - readByte = mappedDevice.readByte(address - base) - else: - readByte = self.memory[address] - - #print "Read byte %s from %s" % (hex(readByte) , hex(address)) - return readByte - - def writeByte(self, address, value): - # TODO - add memory mapping - if address < 0 or address > 0xffff: - raise InvalidAddressException(address) - - if value < 0 or value > 0xff: - raise ValueOutOfRange(value) - - map = self.getMapFor(address) - if map != None: - base = map.base() - mappedDevice = map.callback - mappedDevice.writeByte(address - base, value) - else: - self.memory[address] = value - - def readSignedByte(self, address): - b = self.readByte(address) - return unpack("b", chr(b))[0] - - def readWord(self, address): +''' +Created on 12 Oct 2011 + +@author: chris.whitworth +''' +from struct import unpack + +class InvalidAddressException(Exception): + def __init__(self, address): + self.address = address + + def __repr__(self): + return "Invalid address: %s" % hex(self.address) + +class ValueOutOfRange(Exception): + def __init__(self, value): + self.value = value + + def __repr__(self): + return "Value out of range: %s" % hex(self.value) + +class Memory(object): + class Map(object): + def __init__(self, range, callback): + self.range = range + self.callback = callback + + def base(self): + return self.range[0] + + def end(self): + return self.range[1] + + def isInMap(self, address): + return True if address >= self.base() and address < self.end() else False + + MEMORYSIZE = 64 * 1024 + def __init__(self): + self.memory = bytearray(self.MEMORYSIZE) + self.protection = bytearray(self.MEMORYSIZE) + self.maps = [] + + def map(self, range, callback): + self.maps.append( self.Map(range, callback) ) + + def unmap(self, range): + raise BaseException("Cannae do this") + + def getMapFor(self, address): + maps = [ map for map in self.maps if map.isInMap(address) ] + if len(maps) != 0: + return maps[-1] + else: + return None + + def readByte(self, address): + # TODO - add memory mapping + if address < 0 or address > 0xffff: + raise InvalidAddressException(address) + + map = self.getMapFor(address) + + if map != None: + base = map.base() + mappedDevice = map.callback + readByte = mappedDevice.readByte(address - base) + else: + readByte = self.memory[address] + + #print "Read byte %s from %s" % (hex(readByte) , hex(address)) + return readByte + + def writeByte(self, address, value): + # TODO - add memory mapping + if address < 0 or address > 0xffff: + raise InvalidAddressException(address) + + if value < 0 or value > 0xff: + raise ValueOutOfRange(value) + + map = self.getMapFor(address) + if map != None: + base = map.base() + mappedDevice = map.callback + mappedDevice.writeByte(address - base, value) + else: + self.memory[address] = value + + def readSignedByte(self, address): + b = self.readByte(address) + return unpack("b", chr(b))[0] + + def readWord(self, address): return self.readByte(address) + (self.readByte(address + 1) << 8) \ No newline at end of file diff --git a/CPU/Registers.py b/CPU/Registers.py index abadf14..71769c6 100644 --- a/CPU/Registers.py +++ b/CPU/Registers.py @@ -1,64 +1,63 @@ -''' -Created on 12 Oct 2011 - -@author: chris.whitworth -''' - -class RegisterBank(object): - def __init__(self): - self.pc = 0x0000 - self.sp = 0xff - self.a = 0x00 - self.x = 0x00 - self.y = 0x00 - self.nextPC = 0x0000 - - self.carry = False - self.zero = False - self.int = False - self.dec = False - self.brk = False - self.overflow = False - self.negative = False - - def ps(self): - return ( (1 if self.carry else 0) | - (2 if self.zero else 0) | - (4 if self.int else 0) | - (8 if self.dec else 0) | - (16 if self.brk else 0) | - (64 if self.overflow else 0) | - (128 if self.negative else 0) ) - - def setPS(self, value): - self.carry = (value & 0x1) != 0 - self.zero = (value & 0x2) != 0 - self.int = (value & 0x4) != 0 - self.dec = (value & 0x8) != 0 - self.brk = (value & 0x10) != 0 - self.overflow = (value & 0x40) != 0 - self.negative = (value & 0x80) != 0 - - def reset(self): - self.x = 0 - self.a = 0 - self.y = 0 - self.pc = 0 - self.nextPC = 0 - self.sp = 0xff - self.setPS(0) - - def status(self): - - - print "%s%s.%s%s%s%s%s" % ( - "N" if self.negative else "-", - "V" if self.overflow else "-", - "B" if self.brk else "-", - "D" if self.dec else "-", - "I" if self.int else "-", - "Z" if self.zero else "-", - "C" if self.carry else "-"), - print "A: %s X: %s Y: %s" % (hex(self.a), hex(self.x), hex(self.y)), - print "PC: %s SP: %s" % (hex(self.pc), hex(self.sp)) - \ No newline at end of file +''' +Created on 12 Oct 2011 + +@author: chris.whitworth +''' + +class RegisterBank(object): + def __init__(self): + self.pc = 0x0000 + self.sp = 0xff + self.a = 0x00 + self.x = 0x00 + self.y = 0x00 + self.nextPC = 0x0000 + + self.carry = False + self.zero = False + self.int = False + self.dec = False + self.brk = False + self.overflow = False + self.negative = False + + def ps(self): + return ( (1 if self.carry else 0) | + (2 if self.zero else 0) | + (4 if self.int else 0) | + (8 if self.dec else 0) | + (16 if self.brk else 0) | + (64 if self.overflow else 0) | + (128 if self.negative else 0) ) + + def setPS(self, value): + self.carry = (value & 0x1) != 0 + self.zero = (value & 0x2) != 0 + self.int = (value & 0x4) != 0 + self.dec = (value & 0x8) != 0 + self.brk = (value & 0x10) != 0 + self.overflow = (value & 0x40) != 0 + self.negative = (value & 0x80) != 0 + + def reset(self): + self.x = 0 + self.a = 0 + self.y = 0 + self.pc = 0 + self.nextPC = 0 + self.sp = 0xff + self.setPS(0) + + def status(self): + + + print "%s%s.%s%s%s%s%s" % ( + "N" if self.negative else "-", + "V" if self.overflow else "-", + "B" if self.brk else "-", + "D" if self.dec else "-", + "I" if self.int else "-", + "Z" if self.zero else "-", + "C" if self.carry else "-"), + print "A: %s X: %s Y: %s" % (hex(self.a), hex(self.x), hex(self.y)), + print "PC: %s SP: %s" % (hex(self.pc), hex(self.sp)) diff --git a/CPU/Writeback.py b/CPU/Writeback.py index fb3743b..0b0bf67 100644 --- a/CPU/Writeback.py +++ b/CPU/Writeback.py @@ -1,34 +1,34 @@ -''' -Created on 14 Oct 2011 - -@author: chris.whitworth -''' - -class Dispatcher(object): - def __init__(self,memory,registers): - self.mem = memory - self.registers = registers - - def A(self, value, location): - self.registers.a = value - - def X(self, value, location): - self.registers.x = value - - def Y(self, value, location): - self.registers.y = value - - def memory(self, value, location): - self.mem.writeByte(location, value) - - def PC(self, value, location): - self.registers.nextPC = value - - def SP(self, value, location): - self.registers.sp = value - - def PS(self, value, location): - self.registers.setPS(value) - - def NW(self, value, location): +''' +Created on 14 Oct 2011 + +@author: chris.whitworth +''' + +class Dispatcher(object): + def __init__(self,memory,registers): + self.mem = memory + self.registers = registers + + def A(self, value, location): + self.registers.a = value + + def X(self, value, location): + self.registers.x = value + + def Y(self, value, location): + self.registers.y = value + + def memory(self, value, location): + self.mem.writeByte(location, value) + + def PC(self, value, location): + self.registers.nextPC = value + + def SP(self, value, location): + self.registers.sp = value + + def PS(self, value, location): + self.registers.setPS(value) + + def NW(self, value, location): pass \ No newline at end of file diff --git a/Debugging/Combiner.py b/Debugging/Combiner.py index 7704cf3..7efabc0 100644 --- a/Debugging/Combiner.py +++ b/Debugging/Combiner.py @@ -1,11 +1,11 @@ -class Dispatcher(object): - def __init__(self, executors): - self.executors = executors - - def __getattr__(self, name): - def handler(*args, **kwargs): - for e in self.executors: - fn = getattr(e,name) - value = fn(*args, **kwargs) - return value +class Dispatcher(object): + def __init__(self, executors): + self.executors = executors + + def __getattr__(self, name): + def handler(*args, **kwargs): + for e in self.executors: + fn = getattr(e,name) + value = fn(*args, **kwargs) + return value return handler \ No newline at end of file diff --git a/Debugging/ExecutionUnit.py b/Debugging/ExecutionUnit.py index c7de96b..4f81d2b 100644 --- a/Debugging/ExecutionUnit.py +++ b/Debugging/ExecutionUnit.py @@ -1,11 +1,10 @@ - - -class LoggingExecutionUnit(object): - def __init__(self): - pass - - def __getattr__(self, name): - def handler(*args, **kwargs): - print "%s called (%s, %s)" % (name, args, kwargs) - return handler - \ No newline at end of file + + +class LoggingExecutionUnit(object): + def __init__(self): + pass + + def __getattr__(self, name): + def handler(*args, **kwargs): + print "%s called (%s, %s)" % (name, args, kwargs) + return handler diff --git a/Debugging/Writeback.py b/Debugging/Writeback.py index 1d14539..62358af 100644 --- a/Debugging/Writeback.py +++ b/Debugging/Writeback.py @@ -1,30 +1,30 @@ -''' -Created on 14 Oct 2011 - -@author: chris.whitworth -''' - -class LoggingDispatcher(object): - def A(self, value, location): - print "Saving %s to A" % value - - def X(self, value, location): - print "Saving %s to X" % value - - def Y(self, value, location): - print "Saving %s to Y" % value - - def memory(self, value, location): - print "Saving %s to $%s" % (value, hex(location)) - - def PC(self, value, location): - print "Saving %s to the PC" % value - - def SP(self, value, location): - print "Saving %s to the SP" % value - - def PS(self, value, location): - print "Saving %s to the PS" % value - - def NW(self, value, location): +''' +Created on 14 Oct 2011 + +@author: chris.whitworth +''' + +class LoggingDispatcher(object): + def A(self, value, location): + print "Saving %s to A" % value + + def X(self, value, location): + print "Saving %s to X" % value + + def Y(self, value, location): + print "Saving %s to Y" % value + + def memory(self, value, location): + print "Saving %s to $%s" % (value, hex(location)) + + def PC(self, value, location): + print "Saving %s to the PC" % value + + def SP(self, value, location): + print "Saving %s to the SP" % value + + def PS(self, value, location): + print "Saving %s to the PS" % value + + def NW(self, value, location): print "(no writeback)" \ No newline at end of file diff --git a/DisassembleTest.py b/DisassembleTest.py index dae8899..444c542 100644 --- a/DisassembleTest.py +++ b/DisassembleTest.py @@ -1,18 +1,18 @@ -''' -Created on 12 Oct 2011 - -@author: chris.whitworth -''' - -import Disassembler -import ROMs.TestData as TestData - -DecoderTablePath = "insts.csv" - -def main(): - disassembler = Disassembler.Disassembler(DecoderTablePath) - disassembler.disassemble(TestData.testROM1) - - -if __name__ == '__main__': +''' +Created on 12 Oct 2011 + +@author: chris.whitworth +''' + +import Disassembler +import ROMs.TestData as TestData + +DecoderTablePath = "insts.csv" + +def main(): + disassembler = Disassembler.Disassembler(DecoderTablePath) + disassembler.disassemble(TestData.testROM1) + + +if __name__ == '__main__': main() \ No newline at end of file diff --git a/Disassembler.py b/Disassembler.py index f6b45ec..02c75c6 100644 --- a/Disassembler.py +++ b/Disassembler.py @@ -1,239 +1,238 @@ -''' -Created on 12 Oct 2011 - -@author: chris.whitworth -''' -import CPU.Dispatch as Dispatch -import CPU.AddressDispatcher as AddressDispatch -import CPU.InstructionDecoder as Decoder -import CPU.Memory as Memory -import CPU.Registers as Registers -import ArrayMemMapper - -import logging - -class ExecutionUnit(object): - def ADC(self, data): - return "ADC %s" % hex(data) - - def AND(self, data): - return "AND %s" % hex(data) - - def ASL(self, data): - return "ASL %s" % hex(data) - - def BCC(self, data): - return "BCC %s" % hex(data) - - def BCS(self, data): - return "BCS %s" % hex(data) - - def BEQ(self, data): - return "BEQ %s" % hex(data) - - def BIT(self, data): - return "BIT %s" % hex(data) - - def BMI(self, data): - return "BMI %s" % hex(data) - - def BNE(self, data): - return "BNE %s" % hex(data) - - def BPL(self, data): - return "BPL %s" % hex(data) - - def BRK(self, data): - return "BRK" - - def BVC(self, data): - return "BVC %s" % hex(data) - - def BVS(self, data): - return "BVS %s" % hex(data) - - def CLC(self, data): - return "CLC" - - def CLD(self, data): - return "CLD" - - def CLI(self, data): - return "CLI" - - def CLV(self, data): - return "CLV" - - def CMP(self, data): - return "CMP %s" % hex(data) - - def CPX(self, data): - return "CPX %s" % hex(data) - - def CPY(self, data): - return "CPY %s" % hex(data) - - def DEC(self, data): - return "DEC %s" % hex(data) - - def DEX(self, data): - return "DEX" - - def DEY(self, data): - return "DEY" - - def EOR(self, data): - return "EOR %s" % hex(data) - - def INC(self, data): - return "INC %s" % hex(data) - - def INX(self, data): - return "INX" - - def INY(self, data): - return "INY" - - def JMP(self, data): - return "JMP %s" % hex(data) - - def JSR(self, data): - return "JSR %s" % hex(data) - - def LDA(self, data): - return "LDA %s" % hex(data) - - def LDX(self, data): - return "LDX %s" % hex(data) - - def LDY(self, data): - return "LDY %s" % hex(data) - - def LSR(self, data): - return "LSR %s" % hex(data) - - def NOP(self, data): - return "NOP" - - def ORA(self, data): - return "ORA %s" % hex(data) - - def PHA(self, data): - return "PHA" - - def PHP(self, data): - return "PHP" - - def PLA(self, data): - return "PLA" - - def PLP(self, data): - return "PLP" - - def ROL(self, data): - return "ROL %s" % hex(data) - - def ROR(self, data): - return "ROR %s" % hex(data) - - def RTI(self, data): - return "RTI" - - def RTS(self, data): - return "RTS" - - def SBC(self, data): - return "SBC %s" % hex(data) - - def SEC(self, data): - return "SEC" - - def SED(self, data): - return "SED" - - def SEI(self, data): - return "SEI" - - def STA(self, data): - return "STA %s" % hex(data) - - def STX(self, data): - return "STX %s" % hex(data) - - def STY(self, data): - return "STY %s" % hex(data) - - def TAX(self, data): - return "TAX" - - def TAY(self, data): - return "TAY" - - def TSX(self, data): - return "TSX" - - def TXA(self, data): - return "TXA" - - def TXS(self, data): - return "TXS" - - def TYA(self, data): - return "TYA" - - def UNDEFINED(self, data): - return "UNDEFINED" - -class WritebackDispatcher(object): - def A(self, value, location): - pass - - def X(self, value, location): - pass - - def Y(self, value, location): - pass - - def memory(self, value, location): - pass - - def PC(self, value, location): - pass - - def SP(self, value, location): - pass - - def PS(self, value, location): - pass - - def NW(self, value, location): - pass - -class Disassembler(object): - def __init__(self, decoderTablePath): - executionDispatcher = ExecutionUnit() - self.memory = Memory.Memory() - self.registers = Registers.RegisterBank() - addressDispatcher = AddressDispatch.AddressDispatcher(self.memory, self.registers) - writebackDispatcher = WritebackDispatcher() - decoder = Decoder.Decoder(decoderTablePath) - self.dispatch = Dispatch.Dispatcher(decoder, addressDispatcher, executionDispatcher, writebackDispatcher, self.memory, self.registers) - - class Generator(object): - def __init__(self, dispatcher): - self.dispatcher = dispatcher - - def __iter__(self): - return self.next() - - def next(self): - while True: - yield self.dispatcher.dispatch() - - def disassemble(self, data): - self.memory.map( (0, len(data)), ArrayMemMapper.Mapper(data)) - generator = self.Generator(self.dispatch) - for decode in generator: - print "%s " % (self.registers.pc), - print ": %s " % (decode) - \ No newline at end of file +''' +Created on 12 Oct 2011 + +@author: chris.whitworth +''' +import CPU.Dispatch as Dispatch +import CPU.AddressDispatcher as AddressDispatch +import CPU.InstructionDecoder as Decoder +import CPU.Memory as Memory +import CPU.Registers as Registers +import ArrayMemMapper + +import logging + +class ExecutionUnit(object): + def ADC(self, data): + return "ADC %s" % hex(data) + + def AND(self, data): + return "AND %s" % hex(data) + + def ASL(self, data): + return "ASL %s" % hex(data) + + def BCC(self, data): + return "BCC %s" % hex(data) + + def BCS(self, data): + return "BCS %s" % hex(data) + + def BEQ(self, data): + return "BEQ %s" % hex(data) + + def BIT(self, data): + return "BIT %s" % hex(data) + + def BMI(self, data): + return "BMI %s" % hex(data) + + def BNE(self, data): + return "BNE %s" % hex(data) + + def BPL(self, data): + return "BPL %s" % hex(data) + + def BRK(self, data): + return "BRK" + + def BVC(self, data): + return "BVC %s" % hex(data) + + def BVS(self, data): + return "BVS %s" % hex(data) + + def CLC(self, data): + return "CLC" + + def CLD(self, data): + return "CLD" + + def CLI(self, data): + return "CLI" + + def CLV(self, data): + return "CLV" + + def CMP(self, data): + return "CMP %s" % hex(data) + + def CPX(self, data): + return "CPX %s" % hex(data) + + def CPY(self, data): + return "CPY %s" % hex(data) + + def DEC(self, data): + return "DEC %s" % hex(data) + + def DEX(self, data): + return "DEX" + + def DEY(self, data): + return "DEY" + + def EOR(self, data): + return "EOR %s" % hex(data) + + def INC(self, data): + return "INC %s" % hex(data) + + def INX(self, data): + return "INX" + + def INY(self, data): + return "INY" + + def JMP(self, data): + return "JMP %s" % hex(data) + + def JSR(self, data): + return "JSR %s" % hex(data) + + def LDA(self, data): + return "LDA %s" % hex(data) + + def LDX(self, data): + return "LDX %s" % hex(data) + + def LDY(self, data): + return "LDY %s" % hex(data) + + def LSR(self, data): + return "LSR %s" % hex(data) + + def NOP(self, data): + return "NOP" + + def ORA(self, data): + return "ORA %s" % hex(data) + + def PHA(self, data): + return "PHA" + + def PHP(self, data): + return "PHP" + + def PLA(self, data): + return "PLA" + + def PLP(self, data): + return "PLP" + + def ROL(self, data): + return "ROL %s" % hex(data) + + def ROR(self, data): + return "ROR %s" % hex(data) + + def RTI(self, data): + return "RTI" + + def RTS(self, data): + return "RTS" + + def SBC(self, data): + return "SBC %s" % hex(data) + + def SEC(self, data): + return "SEC" + + def SED(self, data): + return "SED" + + def SEI(self, data): + return "SEI" + + def STA(self, data): + return "STA %s" % hex(data) + + def STX(self, data): + return "STX %s" % hex(data) + + def STY(self, data): + return "STY %s" % hex(data) + + def TAX(self, data): + return "TAX" + + def TAY(self, data): + return "TAY" + + def TSX(self, data): + return "TSX" + + def TXA(self, data): + return "TXA" + + def TXS(self, data): + return "TXS" + + def TYA(self, data): + return "TYA" + + def UNDEFINED(self, data): + return "UNDEFINED" + +class WritebackDispatcher(object): + def A(self, value, location): + pass + + def X(self, value, location): + pass + + def Y(self, value, location): + pass + + def memory(self, value, location): + pass + + def PC(self, value, location): + pass + + def SP(self, value, location): + pass + + def PS(self, value, location): + pass + + def NW(self, value, location): + pass + +class Disassembler(object): + def __init__(self, decoderTablePath): + executionDispatcher = ExecutionUnit() + self.memory = Memory.Memory() + self.registers = Registers.RegisterBank() + addressDispatcher = AddressDispatch.AddressDispatcher(self.memory, self.registers) + writebackDispatcher = WritebackDispatcher() + decoder = Decoder.Decoder(decoderTablePath) + self.dispatch = Dispatch.Dispatcher(decoder, addressDispatcher, executionDispatcher, writebackDispatcher, self.memory, self.registers) + + class Generator(object): + def __init__(self, dispatcher): + self.dispatcher = dispatcher + + def __iter__(self): + return self.next() + + def next(self): + while True: + yield self.dispatcher.dispatch() + + def disassemble(self, data): + self.memory.map( (0, len(data)), ArrayMemMapper.Mapper(data)) + generator = self.Generator(self.dispatch) + for decode in generator: + print "%s " % (self.registers.pc), + print ": %s " % (decode) diff --git a/MemoryTests.py b/MemoryTests.py index d5db845..669d266 100644 --- a/MemoryTests.py +++ b/MemoryTests.py @@ -1,100 +1,99 @@ -import unittest -import CPU.Memory - -class MockMapper(object): - def __init__(self): - self.lastByteRead = None - self.lastByteWritten = (None, None) - - def readByte(self, address): - self.lastByteRead = address - return 0 - - def writeByte(self, address, value): - self.lastByteWritten = (address, value) - -class MemoryTestsSimple(unittest.TestCase): - def setUp(self): - self.mem = CPU.Memory.Memory() - - def test_zeroOnReset(self): - for address in range(self.mem.MEMORYSIZE): - self.assertEqual(self.mem.readByte(address), 0) - - def test_writeEveryByte(self): - for address in range(self.mem.MEMORYSIZE): - self.mem.writeByte(address, 1) - self.assertEqual(self.mem.readByte(address), 1) - -class MappingTestSimple(unittest.TestCase): - def setUp(self): - self.mem = CPU.Memory.Memory() - self.mapper = MockMapper() - self.mem.map( (0, 0x100), self.mapper) - - def test_readInRange(self): - for address in range(0x100): - self.mem.readByte(address) - self.assertEqual(self.mapper.lastByteRead, address) - - def test_writeInRange(self): - for address in range(0x100): - self.mem.writeByte(address, address ^ 0xff) - self.assertEqual(self.mapper.lastByteWritten, (address, address ^ 0xff)) - - def test_readOutOfRange(self): - for address in range(0x100, self.mem.MEMORYSIZE): - self.mem.readByte(address) - self.assertEqual(self.mapper.lastByteRead, None) - - def test_writeOutOfRange(self): - for address in range(0x100, self.mem.MEMORYSIZE): - self.mem.writeByte(address, (address & 0xff) ^ 0xff) - self.assertEqual(self.mapper.lastByteWritten, (None, None)) - -class OverlaidMappingTests(unittest.TestCase): - def setUp(self): - self.mem = CPU.Memory.Memory() - - self.firstMapper = MockMapper() - self.secondMapper = MockMapper() - - self.mem.map( (0, 0x200), self.firstMapper) - self.mem.map( (0x100, 0x300), self.secondMapper) - - def test_readInFirstMap(self): - for address in range(0, 0x100): - self.mem.readByte(address) - self.assertEqual(self.firstMapper.lastByteRead, address) - self.assertEqual(self.secondMapper.lastByteRead, None) - - def test_writeInFirstMap(self): - for address in range(0, 0x100): - self.mem.writeByte(address, address ^ 0xff) - self.assertEqual(self.firstMapper.lastByteWritten, (address, address ^ 0xff)) - self.assertEqual(self.secondMapper.lastByteWritten, (None, None)) - - def test_readInSecondMapOverlaidOnFirstMap(self): - for address in range(0x100, 0x200): - self.mem.readByte(address) - self.assertEqual(self.firstMapper.lastByteRead, None) - self.assertEqual(self.secondMapper.lastByteRead, address - 0x100) - - def test_writeInSecondMapOverlaidOnFirstMap(self): - for address in range(0x100, 0x200): - self.mem.writeByte(address, (address & 0xff) ^ 0xff) - self.assertEqual(self.firstMapper.lastByteWritten, (None, None)) - self.assertEqual(self.secondMapper.lastByteWritten, (address - 0x100, (address & 0xff) ^ 0xff)) - - def test_readInSecondMap(self): - for address in range(0x200, 0x300): - self.mem.readByte(address) - self.assertEqual(self.firstMapper.lastByteRead, None) - self.assertEqual(self.secondMapper.lastByteRead, address - 0x100) - - def test_writeInSecondMap(self): - for address in range(0x200, 0x300): - self.mem.writeByte(address, (address & 0xff) ^ 0xff) - self.assertEqual(self.firstMapper.lastByteWritten, (None, None)) - self.assertEqual(self.secondMapper.lastByteWritten, (address - 0x100, (address & 0xff) ^ 0xff)) - \ No newline at end of file +import unittest +import CPU.Memory + +class MockMapper(object): + def __init__(self): + self.lastByteRead = None + self.lastByteWritten = (None, None) + + def readByte(self, address): + self.lastByteRead = address + return 0 + + def writeByte(self, address, value): + self.lastByteWritten = (address, value) + +class MemoryTestsSimple(unittest.TestCase): + def setUp(self): + self.mem = CPU.Memory.Memory() + + def test_zeroOnReset(self): + for address in range(self.mem.MEMORYSIZE): + self.assertEqual(self.mem.readByte(address), 0) + + def test_writeEveryByte(self): + for address in range(self.mem.MEMORYSIZE): + self.mem.writeByte(address, 1) + self.assertEqual(self.mem.readByte(address), 1) + +class MappingTestSimple(unittest.TestCase): + def setUp(self): + self.mem = CPU.Memory.Memory() + self.mapper = MockMapper() + self.mem.map( (0, 0x100), self.mapper) + + def test_readInRange(self): + for address in range(0x100): + self.mem.readByte(address) + self.assertEqual(self.mapper.lastByteRead, address) + + def test_writeInRange(self): + for address in range(0x100): + self.mem.writeByte(address, address ^ 0xff) + self.assertEqual(self.mapper.lastByteWritten, (address, address ^ 0xff)) + + def test_readOutOfRange(self): + for address in range(0x100, self.mem.MEMORYSIZE): + self.mem.readByte(address) + self.assertEqual(self.mapper.lastByteRead, None) + + def test_writeOutOfRange(self): + for address in range(0x100, self.mem.MEMORYSIZE): + self.mem.writeByte(address, (address & 0xff) ^ 0xff) + self.assertEqual(self.mapper.lastByteWritten, (None, None)) + +class OverlaidMappingTests(unittest.TestCase): + def setUp(self): + self.mem = CPU.Memory.Memory() + + self.firstMapper = MockMapper() + self.secondMapper = MockMapper() + + self.mem.map( (0, 0x200), self.firstMapper) + self.mem.map( (0x100, 0x300), self.secondMapper) + + def test_readInFirstMap(self): + for address in range(0, 0x100): + self.mem.readByte(address) + self.assertEqual(self.firstMapper.lastByteRead, address) + self.assertEqual(self.secondMapper.lastByteRead, None) + + def test_writeInFirstMap(self): + for address in range(0, 0x100): + self.mem.writeByte(address, address ^ 0xff) + self.assertEqual(self.firstMapper.lastByteWritten, (address, address ^ 0xff)) + self.assertEqual(self.secondMapper.lastByteWritten, (None, None)) + + def test_readInSecondMapOverlaidOnFirstMap(self): + for address in range(0x100, 0x200): + self.mem.readByte(address) + self.assertEqual(self.firstMapper.lastByteRead, None) + self.assertEqual(self.secondMapper.lastByteRead, address - 0x100) + + def test_writeInSecondMapOverlaidOnFirstMap(self): + for address in range(0x100, 0x200): + self.mem.writeByte(address, (address & 0xff) ^ 0xff) + self.assertEqual(self.firstMapper.lastByteWritten, (None, None)) + self.assertEqual(self.secondMapper.lastByteWritten, (address - 0x100, (address & 0xff) ^ 0xff)) + + def test_readInSecondMap(self): + for address in range(0x200, 0x300): + self.mem.readByte(address) + self.assertEqual(self.firstMapper.lastByteRead, None) + self.assertEqual(self.secondMapper.lastByteRead, address - 0x100) + + def test_writeInSecondMap(self): + for address in range(0x200, 0x300): + self.mem.writeByte(address, (address & 0xff) ^ 0xff) + self.assertEqual(self.firstMapper.lastByteWritten, (None, None)) + self.assertEqual(self.secondMapper.lastByteWritten, (address - 0x100, (address & 0xff) ^ 0xff)) diff --git a/ROArrayMemMapper.py b/ROArrayMemMapper.py index c15c634..7bc3ddd 100644 --- a/ROArrayMemMapper.py +++ b/ROArrayMemMapper.py @@ -1,15 +1,15 @@ -''' -Created on 13 Oct 2011 - -@author: chris.whitworth -''' - -class Mapper(object): - def __init__(self, data): - self.data = data - - def readByte(self, address): - return self.data[address] - - def writeByte(self, address, value): +''' +Created on 13 Oct 2011 + +@author: chris.whitworth +''' + +class Mapper(object): + def __init__(self, data): + self.data = data + + def readByte(self, address): + return self.data[address] + + def writeByte(self, address, value): pass \ No newline at end of file diff --git a/ROMs/TestData.py b/ROMs/TestData.py index a493c5c..73b3a2b 100644 --- a/ROMs/TestData.py +++ b/ROMs/TestData.py @@ -1,56 +1,56 @@ -''' -Created on 13 Oct 2011 - -@author: chris.whitworth -''' - -testROM1 = [ - 0xad, 0x00, 0xff, # LDA &FF00 (a=0xad) - 0x6c, 0x06, 0xff, # JMP (&FF06) - 0x1b, 0xff, # (&FF1B) - 0x49, 0xff, # EOR #255 - 0x60, # RTS - 0xf2, # NXX (NOP) - 0xa9, 7, # LDA #7 - 0x48, # PHA - 0xa9, 2, # LDA #2 - 0x48, # PHA - 0xba, # TSX - 0xe8, # INX - 0x9a, # TXS - 0x68, # PLA - 0xa8, # TAY - 0x8c, 0x00, 0x02, # STY &200 - 0x40, # RTI - 0x29, 0x0f, # AND #&0F (a=0x0d) - 0x0a, # ASL A (a=0x1a) - 0x0a, # ASL A (a=0x34) - 0x0a, # ASL A (a=0x68) - 0x0a, # ASL A (a=0xd0) - 0x0a, # ASL A (a=0xa0 c=1) - 0xb0, 2, # BCS +2 (to the STA) - 0xea, 0xea, # NOP:NOP - 0x85, 0xff, # STA &FF - 0x18, # CLC - 0xca, 0x88, # DEX : DEY - 0xa9, 1, # LDA #1 - 0x20, 0x08, 0xff, # JSR &FF08 - 0xd6, 0, # DEC &00, X - 0xa5, 0xff, # LDA &FF - 0x2c, 0x01, 0xff, # BIT &FF01 (z = 1) - 0xf0, 4, # BEQ +4 - 0x0, # BRK - 0x38, # SEC - 0xb0, 2, # BCS +2 (HCF) - 0xf0, 0xfa, # BEQ -6 (to the BRK) - 0xff ] # HCF - -testROM2 = [ - 0x69, 0x34, # ADC #&34 - 0x65, 0x34, # ADC &34 (zp) - 0x75, 0x34, # ADC &34, X - 0x6d, 0x34, 0x00, # ADC &0034 - 0x7d, 0x34, 0x00, # ADC &0034, X - 0x79, 0x34, 0x00, # ADC &0034, Y - +''' +Created on 13 Oct 2011 + +@author: chris.whitworth +''' + +testROM1 = [ + 0xad, 0x00, 0xff, # LDA &FF00 (a=0xad) + 0x6c, 0x06, 0xff, # JMP (&FF06) + 0x1b, 0xff, # (&FF1B) + 0x49, 0xff, # EOR #255 + 0x60, # RTS + 0xf2, # NXX (NOP) + 0xa9, 7, # LDA #7 + 0x48, # PHA + 0xa9, 2, # LDA #2 + 0x48, # PHA + 0xba, # TSX + 0xe8, # INX + 0x9a, # TXS + 0x68, # PLA + 0xa8, # TAY + 0x8c, 0x00, 0x02, # STY &200 + 0x40, # RTI + 0x29, 0x0f, # AND #&0F (a=0x0d) + 0x0a, # ASL A (a=0x1a) + 0x0a, # ASL A (a=0x34) + 0x0a, # ASL A (a=0x68) + 0x0a, # ASL A (a=0xd0) + 0x0a, # ASL A (a=0xa0 c=1) + 0xb0, 2, # BCS +2 (to the STA) + 0xea, 0xea, # NOP:NOP + 0x85, 0xff, # STA &FF + 0x18, # CLC + 0xca, 0x88, # DEX : DEY + 0xa9, 1, # LDA #1 + 0x20, 0x08, 0xff, # JSR &FF08 + 0xd6, 0, # DEC &00, X + 0xa5, 0xff, # LDA &FF + 0x2c, 0x01, 0xff, # BIT &FF01 (z = 1) + 0xf0, 4, # BEQ +4 + 0x0, # BRK + 0x38, # SEC + 0xb0, 2, # BCS +2 (HCF) + 0xf0, 0xfa, # BEQ -6 (to the BRK) + 0xff ] # HCF + +testROM2 = [ + 0x69, 0x34, # ADC #&34 + 0x65, 0x34, # ADC &34 (zp) + 0x75, 0x34, # ADC &34, X + 0x6d, 0x34, 0x00, # ADC &0034 + 0x7d, 0x34, 0x00, # ADC &0034, X + 0x79, 0x34, 0x00, # ADC &0034, Y + ] \ No newline at end of file From e33331c921eb6fa3a08016bc51c3d1f69f02dca2 Mon Sep 17 00:00:00 2001 From: Charles Ferguson Date: Sat, 25 Nov 2023 03:57:25 +0000 Subject: [PATCH 02/65] Add Unicorn-like interface. There's now an interface that's similar in style to the Unicorn interface. The intention is that whilst this won't be a drop in for Unicorn, the expectations that you might have from Unicorn, such as the means of accessing registers and memory, and executing code, are similar. --- BBCMicro/System.py | 2 +- CPU/Dispatch.py | 2 +- CPU/Memory.py | 105 +++++++++++++++++++++++- PyBeebU.py | 40 ++++++++++ PyBeebicorn.py | 195 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 341 insertions(+), 3 deletions(-) create mode 100644 PyBeebU.py create mode 100644 PyBeebicorn.py diff --git a/BBCMicro/System.py b/BBCMicro/System.py index 87b03ec..1b644f4 100644 --- a/BBCMicro/System.py +++ b/BBCMicro/System.py @@ -26,4 +26,4 @@ def setPagedROM(self, pagedRom): self.pagedROM.setPagedROM(pagedRom) def tick(self): - self.cpu.dispatch() \ No newline at end of file + self.cpu.dispatch() diff --git a/CPU/Dispatch.py b/CPU/Dispatch.py index 2a4abca..a217360 100644 --- a/CPU/Dispatch.py +++ b/CPU/Dispatch.py @@ -135,4 +135,4 @@ def dispatch(self): def reset(self): self.registers.reset() - self.registers.pc = self.memory.readWord(0xfffc) \ No newline at end of file + self.registers.pc = self.memory.readWord(0xfffc) diff --git a/CPU/Memory.py b/CPU/Memory.py index 5bb2d4d..e06b4d2 100644 --- a/CPU/Memory.py +++ b/CPU/Memory.py @@ -53,6 +53,21 @@ def getMapFor(self, address): else: return None + def getNextMap(self, address): + """ + Find the map that is next, after the address we requested. + + @param address: Address to search for + + @return: next map after the one requested, or None if no other maps present + """ + next_map = None + for map in self.maps: + if map.base() > address: + if not next_map or map.base() < next_map.base(): + next_map = map + return next_map + def readByte(self, address): # TODO - add memory mapping if address < 0 or address > 0xffff: @@ -86,9 +101,97 @@ def writeByte(self, address, value): else: self.memory[address] = value + def readBytes(self, address, size): + """ + Read multiple bytes into a bytearray / mapped region. + """ + if address < 0: + raise InvalidAddressException(address) + if address + size > 0xffff: + raise InvalidAddressException(address + size) + + data = bytearray() + + while size: + map = self.getMapFor(address) + if map: + end = address + size + if end > map.end(): + end = map.end() + mappedDevice = map.callback + base = map.base() + map_data = bytearray([mappedDevice.readByte(offset) for offset in range(address - base, end)]) + data += map_data + + else: + # No mapping region, so this is a regular byte array, + # and we need to find out how far it extends. + map = self.getNextMap(address) + if map: + # there is a following map. + next_start = address - size + else: + next_start = 0x10000 + + end = address + size + if end > next_start: + end = next_start + + data += self.memory[address:end] + + size -= (end - address) + address = end + + return data + + def writeBytes(self, address, value): + """ + Read multiple bytes into a bytearray / mapped region. + """ + size = len(value) + if not isinstance(value): + value = bytearray(value) + + if address < 0: + raise InvalidAddressException(address) + if address + size > 0xffff: + raise InvalidAddressException(address + size) + + while size: + map = self.getMapFor(address) + if map: + end = address + size + if end > map.end(): + end = map.end() + mappedDevice = map.callback + base = map.base() + for index in range(end - address): + mappedDevice.writeByte(address + index - base, value[index]) + else: + # No mapping region, so this is a regular byte array, + # and we need to find out how far it extends. + map = self.getNextMap(address) + if map: + # there is a following map. + next_start = address - size + else: + next_start = 0x10000 + + end = address + size + if end > next_start: + end = next_start + + self.memory[address:end] = value[:end - address] + + value = value[end - address:] + size -= (end - address) + address = end + + return data + def readSignedByte(self, address): b = self.readByte(address) return unpack("b", chr(b))[0] def readWord(self, address): - return self.readByte(address) + (self.readByte(address + 1) << 8) \ No newline at end of file + return self.readByte(address) + (self.readByte(address + 1) << 8) diff --git a/PyBeebU.py b/PyBeebU.py new file mode 100644 index 0000000..518e54b --- /dev/null +++ b/PyBeebU.py @@ -0,0 +1,40 @@ +''' +Created on 12 Oct 2011 + +@author: chris.whitworth +''' + +import sys + +from PyBeebicorn import Pb, PbError, PbConstants + + +class BBC(object): + def __init__(self, pcTrace = False, verbose = False): + self.pb = Pb() + + def go(self, syscalls): + try: + # Register the syscall execution entry points + hooks = [] + for addr, func in syscalls.items(): + hooks.append(self.pb.hook_add(PbConstants.PB_HOOK_CODE, + func, begin=addr, end=addr + 1)) + + self.pb.emu_start(self.pb.reg_read(PbConstants.PB_6502_REG_PC), -1) + finally: + # Deregister the entry points + for hook in hooks: + self.pb.hook_del(hook) + + +def OS_WRCH(pb, address, size, user_data): sys.stdout.write(chr(pb.reg_read(PbConstants.PB_6502_REG_A))) +def OS_RDCH(pb, address, size, user_data): print "OS_RDCH" # Could inject keypresses here maybe? + +if __name__ == "__main__": + OS_WRCH_LOC = 0xe0a4 + OS_RDCH_LOC = 0xdec5 + syscalls = { OS_WRCH_LOC : OS_WRCH, + OS_RDCH_LOC : OS_RDCH } + bbc = BBC() + bbc.go(syscalls) diff --git a/PyBeebicorn.py b/PyBeebicorn.py new file mode 100644 index 0000000..e71b0af --- /dev/null +++ b/PyBeebicorn.py @@ -0,0 +1,195 @@ +""" +Unicorn-like interface for PyBeeb. + +Allows code that was written for Unicorn to work with PyBeeb with minimal +modifications (or just reamapping the variable names). +""" + +import os.path + +import CPU.Memory as Memory +import CPU.Registers as Registers +import CPU.AddressDispatcher as AddressDispatcher +import CPU.Writeback as Writeback +import CPU.ExecutionUnit as ExecutionUnit +import CPU.Dispatch as Dispatch +import CPU.InstructionDecoder as Decoder +import Debugging.Combiner +import Debugging.Writeback +import Debugging.ExecutionUnit +import BBCMicro.System + + +class PbConstants(object): + PB_6502_REG_INVALID = 0 + PB_6502_REG_PC = 1 + PB_6502_REG_SP = 2 + PB_6502_REG_A = 3 + PB_6502_REG_X = 4 + PB_6502_REG_Y = 5 + PB_6502_REG_PS = 6 + + PB_6502_FLAG_CARRY = (1<<0) + PB_6502_FLAG_ZERO = (1<<1) + PB_6502_FLAG_INTDISBLE = (1<<2) + PB_6502_FLAG_DECIMAL = (1<<3) + PB_6502_FLAG_BRK = (1<<4) + PB_6502_FLAG_UNUSED = (1<<5) + PB_6502_FLAG_OVERFLOW = (1<<6) + PB_6502_FLAG_NEGATIVE = (1<<7) + + PB_ERR_OK = 0 + PB_ERR_INSN_INVALID = 10 + PB_ERR_ARG = 15 + + PB_MEM_READ = 16 + PB_MEM_WRITE = 17 + PB_HOOK_CODE = 4 + PB_HOOK_MEM_READ = 1024 + PB_HOOK_MEM_WRITE = 2048 + + +# access to error code via @errno of UcError +class PbError(Exception): + def __init__(self, errno): + self.errno = errno + + def __str__(self): + return "Error %s" % (self.errno,) + + +def pb_version(): + major = 0 + minor = 0 + combined = (major<<8) | minor + return (major, minor, combined) + + +class PbHook(object): + + def __init__(self, pb, callback, user_data=None, begin=1, end=0): + self.pb = pb + self.callback = callback + self.user_data = user_data + self.address = begin + self.end = end + + def __contains__(self, value): + return value >= self.address and value < self.end + + def call(self, *args): + args = list(args) + args.append(self.user_data) + self.callback(self.pb, *args) + + +class Pb(object): + insts_filename = os.path.join(os.path.dirname(__file__), 'insts.csv') + + def __init__(self): + # We only support 6502, so there is no architecture or mode flag. + self.mem = Memory.Memory() + self.reg = Registers.RegisterBank() + addrDispatch = AddressDispatcher.AddressDispatcher(self.mem, self.reg) + + execDispatch = ExecutionUnit.ExecutionDispatcher(self.mem,self.reg) + execLogger = Debugging.ExecutionUnit.LoggingExecutionUnit() + combinedExec = Debugging.Combiner.Dispatcher( (execLogger, execDispatch) ) + + writebackDispatch = Writeback.Dispatcher(self.mem,self.reg) + writebackLogger = Debugging.Writeback.LoggingDispatcher() + combinedWriteback = Debugging.Combiner.Dispatcher( (writebackLogger, writebackDispatch) ) + + decoder = Decoder.Decoder(self.insts_filename) + + dispatch = Dispatch.Dispatcher(decoder, addrDispatch, + execDispatch, writebackDispatch, + self.mem, self.reg) + + self.bbc = BBCMicro.System.Beeb(dispatch) + + self.executing = False + + def write_pc(v): + self.reg.pc = v + + def write_sp(v): + self.reg.sp = v + + def write_a(v): + self.reg.a = v + + def write_x(v): + self.reg.x = v + + def write_y(v): + self.reg.y = v + + self.reg_dispatch = { + PbConstants.PB_6502_REG_PC: (lambda: self.reg.pc, write_pc), + PbConstants.PB_6502_REG_SP: (lambda: self.reg.sp, write_sp), + PbConstants.PB_6502_REG_A: (lambda: self.reg.a, write_a), + PbConstants.PB_6502_REG_X: (lambda: self.reg.x, write_x), + PbConstants.PB_6502_REG_Y: (lambda: self.reg.y, write_y), + PbConstants.PB_6502_REG_PS: (lambda: self.reg.ps(), lambda v: self.reg.setPS(v)), + } + + # Execution hooks - when we hit an address in the range we call the hook + self.hook_exec = [] + + # emulate from @begin, and stop when reaching address @until + def emu_start(self, begin, until, count=0): + insts = 0 + self.executing = True + try: + while self.executing and self.reg.pc != until: + #print "%s: PC: %s" % (insts, hex(self.reg.pc)) + + for hook in self.hook_exec: + if self.reg.pc in hook: + hook.call(self.reg.pc, 1) + + self.bbc.tick() + insts += 1 + if count and insts >= count: + break + finally: + self.executing = False + + # stop emulation + def emu_stop(self): + self.executing = False + + # return the value of a register + def reg_read(self, reg_id): + dispatch = self.reg_dispatch.get(reg_id) + if not dispatch: + raise PbError(ERR_ARG) + + return dispatch[0]() + + # write to a register + def reg_write(self, reg_id, value): + dispatch = self.reg_dispatch.get(reg_id) + if not dispatch: + raise PbError(ERR_ARG) + + dispatch[1](value & 0xFF) + + # read data from memory + def mem_read(self, address, size): + return self.memory.readBytes(address, size) + + # write to memory + def mem_write(self, address, data): + self.memory.writeBytes(address, data) + + def hook_add(self, htype, callback, user_data=None, begin=1, end=0, arg1=0): + hook = PbHook(self, callback, user_data=user_data, begin=begin, end=end) + if htype & PbConstants.PB_HOOK_CODE: + self.hook_exec.append(hook) + return hook + + def hook_del(self, hook): + if hook in self.hook_exec: + self.hook_exec.remove(hook) From 453e5b64578ee20770ed01a79c126c1dddd83a7e Mon Sep 17 00:00:00 2001 From: Charles Ferguson Date: Sat, 25 Nov 2023 04:17:38 +0000 Subject: [PATCH 03/65] Move the entire emulation system into a package. In order to be reusable in other systems, it is better if the whole emulation system be in a package, rather than at the top level of the namespace. This change moves everything into a `pybeeb` package. --- PyBeeb.py | 39 ++++++++++--------- PyBeebU.py | 2 +- ArrayMemMapper.py => pybeeb/ArrayMemMapper.py | 0 {BBCMicro => pybeeb/BBCMicro}/OS.py | 0 {BBCMicro => pybeeb/BBCMicro}/PagedROM.py | 0 {BBCMicro => pybeeb/BBCMicro}/ROM.py | 0 {BBCMicro => pybeeb/BBCMicro}/Sheila.py | 0 {BBCMicro => pybeeb/BBCMicro}/System.py | 0 {BBCMicro => pybeeb/BBCMicro}/__init__.py | 0 {CPU => pybeeb/CPU}/AddressDispatcher.py | 0 {CPU => pybeeb/CPU}/Dispatch.py | 0 {CPU => pybeeb/CPU}/ExecutionUnit.py | 0 {CPU => pybeeb/CPU}/InstructionDecoder.py | 0 {CPU => pybeeb/CPU}/Memory.py | 0 {CPU => pybeeb/CPU}/Registers.py | 0 {CPU => pybeeb/CPU}/Writeback.py | 0 {CPU => pybeeb/CPU}/__init__.py | 0 {Debugging => pybeeb/Debugging}/Combiner.py | 0 .../Debugging}/ExecutionUnit.py | 0 {Debugging => pybeeb/Debugging}/Writeback.py | 0 {Debugging => pybeeb/Debugging}/__init__.py | 0 Disassembler.py => pybeeb/Disassembler.py | 0 PyBeebicorn.py => pybeeb/PyBeebicorn.py | 25 +++++------- .../ROArrayMemMapper.py | 0 pybeeb/__init__.py | 0 insts.csv => pybeeb/insts.csv | 0 26 files changed, 31 insertions(+), 35 deletions(-) rename ArrayMemMapper.py => pybeeb/ArrayMemMapper.py (100%) rename {BBCMicro => pybeeb/BBCMicro}/OS.py (100%) rename {BBCMicro => pybeeb/BBCMicro}/PagedROM.py (100%) rename {BBCMicro => pybeeb/BBCMicro}/ROM.py (100%) rename {BBCMicro => pybeeb/BBCMicro}/Sheila.py (100%) rename {BBCMicro => pybeeb/BBCMicro}/System.py (100%) rename {BBCMicro => pybeeb/BBCMicro}/__init__.py (100%) rename {CPU => pybeeb/CPU}/AddressDispatcher.py (100%) rename {CPU => pybeeb/CPU}/Dispatch.py (100%) rename {CPU => pybeeb/CPU}/ExecutionUnit.py (100%) rename {CPU => pybeeb/CPU}/InstructionDecoder.py (100%) rename {CPU => pybeeb/CPU}/Memory.py (100%) rename {CPU => pybeeb/CPU}/Registers.py (100%) rename {CPU => pybeeb/CPU}/Writeback.py (100%) rename {CPU => pybeeb/CPU}/__init__.py (100%) rename {Debugging => pybeeb/Debugging}/Combiner.py (100%) rename {Debugging => pybeeb/Debugging}/ExecutionUnit.py (100%) rename {Debugging => pybeeb/Debugging}/Writeback.py (100%) rename {Debugging => pybeeb/Debugging}/__init__.py (100%) rename Disassembler.py => pybeeb/Disassembler.py (100%) rename PyBeebicorn.py => pybeeb/PyBeebicorn.py (88%) rename ROArrayMemMapper.py => pybeeb/ROArrayMemMapper.py (100%) create mode 100644 pybeeb/__init__.py rename insts.csv => pybeeb/insts.csv (100%) diff --git a/PyBeeb.py b/PyBeeb.py index 35e8b17..db325b8 100644 --- a/PyBeeb.py +++ b/PyBeeb.py @@ -3,20 +3,23 @@ @author: chris.whitworth ''' +import os import sys -import CPU.Memory as Memory -import CPU.Registers as Registers -import CPU.AddressDispatcher as AddressDispatcher -import CPU.Writeback as Writeback -import CPU.ExecutionUnit as ExecutionUnit -import CPU.Dispatch as Dispatch -import CPU.InstructionDecoder as Decoder -import Debugging.Combiner -import Debugging.Writeback -import Debugging.ExecutionUnit -import BBCMicro.System - -DecodeFilename = "insts.csv" +import pybeeb.CPU.Memory as Memory +import pybeeb.CPU.Registers as Registers +import pybeeb.CPU.AddressDispatcher as AddressDispatcher +import pybeeb.CPU.Writeback as Writeback +import pybeeb.CPU.ExecutionUnit as ExecutionUnit +import pybeeb.CPU.Dispatch as Dispatch +import pybeeb.CPU.InstructionDecoder as Decoder +import pybeeb.Debugging.Combiner +import pybeeb.Debugging.Writeback +import pybeeb.Debugging.ExecutionUnit +import pybeeb.BBCMicro.System +import pybeeb + +DecodeFilename = os.path.join(os.path.dirname(pybeeb.__file__), "insts.csv") + class BBC(object): def __init__(self, pcTrace = False, verbose = False): @@ -25,12 +28,12 @@ def __init__(self, pcTrace = False, verbose = False): addrDispatch = AddressDispatcher.AddressDispatcher(self.mem, self.reg) execDispatch = ExecutionUnit.ExecutionDispatcher(self.mem,self.reg) - execLogger = Debugging.ExecutionUnit.LoggingExecutionUnit() - combinedExec = Debugging.Combiner.Dispatcher( (execLogger, execDispatch) ) + execLogger = pybeeb.Debugging.ExecutionUnit.LoggingExecutionUnit() + combinedExec = pybeeb.Debugging.Combiner.Dispatcher( (execLogger, execDispatch) ) writebackDispatch = Writeback.Dispatcher(self.mem,self.reg) - writebackLogger = Debugging.Writeback.LoggingDispatcher() - combinedWriteback = Debugging.Combiner.Dispatcher( (writebackLogger, writebackDispatch) ) + writebackLogger = pybeeb.Debugging.Writeback.LoggingDispatcher() + combinedWriteback = pybeeb.Debugging.Combiner.Dispatcher( (writebackLogger, writebackDispatch) ) decoder = Decoder.Decoder(DecodeFilename) @@ -47,7 +50,7 @@ def __init__(self, pcTrace = False, verbose = False): execDispatch, writebackDispatch, self.mem, self.reg) - self.bbc = BBCMicro.System.Beeb(dispatch) + self.bbc = pybeeb.BBCMicro.System.Beeb(dispatch) def go(self, syscalls): instr = 0 diff --git a/PyBeebU.py b/PyBeebU.py index 518e54b..2470470 100644 --- a/PyBeebU.py +++ b/PyBeebU.py @@ -6,7 +6,7 @@ import sys -from PyBeebicorn import Pb, PbError, PbConstants +from pybeeb.PyBeebicorn import Pb, PbError, PbConstants class BBC(object): diff --git a/ArrayMemMapper.py b/pybeeb/ArrayMemMapper.py similarity index 100% rename from ArrayMemMapper.py rename to pybeeb/ArrayMemMapper.py diff --git a/BBCMicro/OS.py b/pybeeb/BBCMicro/OS.py similarity index 100% rename from BBCMicro/OS.py rename to pybeeb/BBCMicro/OS.py diff --git a/BBCMicro/PagedROM.py b/pybeeb/BBCMicro/PagedROM.py similarity index 100% rename from BBCMicro/PagedROM.py rename to pybeeb/BBCMicro/PagedROM.py diff --git a/BBCMicro/ROM.py b/pybeeb/BBCMicro/ROM.py similarity index 100% rename from BBCMicro/ROM.py rename to pybeeb/BBCMicro/ROM.py diff --git a/BBCMicro/Sheila.py b/pybeeb/BBCMicro/Sheila.py similarity index 100% rename from BBCMicro/Sheila.py rename to pybeeb/BBCMicro/Sheila.py diff --git a/BBCMicro/System.py b/pybeeb/BBCMicro/System.py similarity index 100% rename from BBCMicro/System.py rename to pybeeb/BBCMicro/System.py diff --git a/BBCMicro/__init__.py b/pybeeb/BBCMicro/__init__.py similarity index 100% rename from BBCMicro/__init__.py rename to pybeeb/BBCMicro/__init__.py diff --git a/CPU/AddressDispatcher.py b/pybeeb/CPU/AddressDispatcher.py similarity index 100% rename from CPU/AddressDispatcher.py rename to pybeeb/CPU/AddressDispatcher.py diff --git a/CPU/Dispatch.py b/pybeeb/CPU/Dispatch.py similarity index 100% rename from CPU/Dispatch.py rename to pybeeb/CPU/Dispatch.py diff --git a/CPU/ExecutionUnit.py b/pybeeb/CPU/ExecutionUnit.py similarity index 100% rename from CPU/ExecutionUnit.py rename to pybeeb/CPU/ExecutionUnit.py diff --git a/CPU/InstructionDecoder.py b/pybeeb/CPU/InstructionDecoder.py similarity index 100% rename from CPU/InstructionDecoder.py rename to pybeeb/CPU/InstructionDecoder.py diff --git a/CPU/Memory.py b/pybeeb/CPU/Memory.py similarity index 100% rename from CPU/Memory.py rename to pybeeb/CPU/Memory.py diff --git a/CPU/Registers.py b/pybeeb/CPU/Registers.py similarity index 100% rename from CPU/Registers.py rename to pybeeb/CPU/Registers.py diff --git a/CPU/Writeback.py b/pybeeb/CPU/Writeback.py similarity index 100% rename from CPU/Writeback.py rename to pybeeb/CPU/Writeback.py diff --git a/CPU/__init__.py b/pybeeb/CPU/__init__.py similarity index 100% rename from CPU/__init__.py rename to pybeeb/CPU/__init__.py diff --git a/Debugging/Combiner.py b/pybeeb/Debugging/Combiner.py similarity index 100% rename from Debugging/Combiner.py rename to pybeeb/Debugging/Combiner.py diff --git a/Debugging/ExecutionUnit.py b/pybeeb/Debugging/ExecutionUnit.py similarity index 100% rename from Debugging/ExecutionUnit.py rename to pybeeb/Debugging/ExecutionUnit.py diff --git a/Debugging/Writeback.py b/pybeeb/Debugging/Writeback.py similarity index 100% rename from Debugging/Writeback.py rename to pybeeb/Debugging/Writeback.py diff --git a/Debugging/__init__.py b/pybeeb/Debugging/__init__.py similarity index 100% rename from Debugging/__init__.py rename to pybeeb/Debugging/__init__.py diff --git a/Disassembler.py b/pybeeb/Disassembler.py similarity index 100% rename from Disassembler.py rename to pybeeb/Disassembler.py diff --git a/PyBeebicorn.py b/pybeeb/PyBeebicorn.py similarity index 88% rename from PyBeebicorn.py rename to pybeeb/PyBeebicorn.py index e71b0af..abbdf2c 100644 --- a/PyBeebicorn.py +++ b/pybeeb/PyBeebicorn.py @@ -7,17 +7,15 @@ import os.path -import CPU.Memory as Memory -import CPU.Registers as Registers -import CPU.AddressDispatcher as AddressDispatcher -import CPU.Writeback as Writeback -import CPU.ExecutionUnit as ExecutionUnit -import CPU.Dispatch as Dispatch -import CPU.InstructionDecoder as Decoder -import Debugging.Combiner -import Debugging.Writeback -import Debugging.ExecutionUnit -import BBCMicro.System +from .CPU import Memory as Memory +from .CPU import Registers as Registers +from .CPU import AddressDispatcher as AddressDispatcher +from .CPU import Writeback as Writeback +from .CPU import ExecutionUnit as ExecutionUnit +from .CPU import Dispatch as Dispatch +from .CPU import InstructionDecoder as Decoder +from . import BBCMicro +from .BBCMicro import System as BBCMicroSystem class PbConstants(object): @@ -93,12 +91,7 @@ def __init__(self): addrDispatch = AddressDispatcher.AddressDispatcher(self.mem, self.reg) execDispatch = ExecutionUnit.ExecutionDispatcher(self.mem,self.reg) - execLogger = Debugging.ExecutionUnit.LoggingExecutionUnit() - combinedExec = Debugging.Combiner.Dispatcher( (execLogger, execDispatch) ) - writebackDispatch = Writeback.Dispatcher(self.mem,self.reg) - writebackLogger = Debugging.Writeback.LoggingDispatcher() - combinedWriteback = Debugging.Combiner.Dispatcher( (writebackLogger, writebackDispatch) ) decoder = Decoder.Decoder(self.insts_filename) diff --git a/ROArrayMemMapper.py b/pybeeb/ROArrayMemMapper.py similarity index 100% rename from ROArrayMemMapper.py rename to pybeeb/ROArrayMemMapper.py diff --git a/pybeeb/__init__.py b/pybeeb/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/insts.csv b/pybeeb/insts.csv similarity index 100% rename from insts.csv rename to pybeeb/insts.csv From 65335c15a945664157d7d74112b5655e826f5e09 Mon Sep 17 00:00:00 2001 From: Charles Ferguson Date: Sat, 25 Nov 2023 04:35:07 +0000 Subject: [PATCH 04/65] Fix up tests to run with the new structure. The tests hadn't been updated to run in the new packaged structure. --- DisassembleTest.py | 8 ++- MemoryTests.py | 12 ++-- pybeeb/Disassembler.py | 158 +++++++++++++++++++++-------------------- 3 files changed, 93 insertions(+), 85 deletions(-) diff --git a/DisassembleTest.py b/DisassembleTest.py index 444c542..ec29f2b 100644 --- a/DisassembleTest.py +++ b/DisassembleTest.py @@ -4,13 +4,15 @@ @author: chris.whitworth ''' -import Disassembler +import os + +import pybeeb.Disassembler import ROMs.TestData as TestData -DecoderTablePath = "insts.csv" +DecodeFilename = os.path.join(os.path.dirname(pybeeb.__file__), "insts.csv") def main(): - disassembler = Disassembler.Disassembler(DecoderTablePath) + disassembler = pybeeb.Disassembler.Disassembler(DecodeFilename) disassembler.disassemble(TestData.testROM1) diff --git a/MemoryTests.py b/MemoryTests.py index 669d266..a236130 100644 --- a/MemoryTests.py +++ b/MemoryTests.py @@ -1,5 +1,5 @@ import unittest -import CPU.Memory +import pybeeb.CPU.Memory class MockMapper(object): def __init__(self): @@ -15,7 +15,7 @@ def writeByte(self, address, value): class MemoryTestsSimple(unittest.TestCase): def setUp(self): - self.mem = CPU.Memory.Memory() + self.mem = pybeeb.CPU.Memory.Memory() def test_zeroOnReset(self): for address in range(self.mem.MEMORYSIZE): @@ -28,7 +28,7 @@ def test_writeEveryByte(self): class MappingTestSimple(unittest.TestCase): def setUp(self): - self.mem = CPU.Memory.Memory() + self.mem = pybeeb.CPU.Memory.Memory() self.mapper = MockMapper() self.mem.map( (0, 0x100), self.mapper) @@ -54,7 +54,7 @@ def test_writeOutOfRange(self): class OverlaidMappingTests(unittest.TestCase): def setUp(self): - self.mem = CPU.Memory.Memory() + self.mem = pybeeb.CPU.Memory.Memory() self.firstMapper = MockMapper() self.secondMapper = MockMapper() @@ -97,3 +97,7 @@ def test_writeInSecondMap(self): self.mem.writeByte(address, (address & 0xff) ^ 0xff) self.assertEqual(self.firstMapper.lastByteWritten, (None, None)) self.assertEqual(self.secondMapper.lastByteWritten, (address - 0x100, (address & 0xff) ^ 0xff)) + + +if __name__ == '__main__': + unittest.main() diff --git a/pybeeb/Disassembler.py b/pybeeb/Disassembler.py index 02c75c6..72aa8c4 100644 --- a/pybeeb/Disassembler.py +++ b/pybeeb/Disassembler.py @@ -3,187 +3,188 @@ @author: chris.whitworth ''' -import CPU.Dispatch as Dispatch -import CPU.AddressDispatcher as AddressDispatch -import CPU.InstructionDecoder as Decoder -import CPU.Memory as Memory -import CPU.Registers as Registers -import ArrayMemMapper +import pybeeb.CPU.Dispatch +import pybeeb.CPU.AddressDispatcher as AddressDispatch +import pybeeb.CPU.InstructionDecoder as Decoder +import pybeeb.CPU.Memory +import pybeeb.CPU.Registers +import pybeeb.ArrayMemMapper as ArrayMemMapper +from . import CPU -import logging class ExecutionUnit(object): - def ADC(self, data): + def ADC(self, data, address): return "ADC %s" % hex(data) - def AND(self, data): + def AND(self, data, address): return "AND %s" % hex(data) - def ASL(self, data): + def ASL(self, data, address): return "ASL %s" % hex(data) - def BCC(self, data): - return "BCC %s" % hex(data) + def BCC(self, data, address): + return "BCC %s" % hex(address) - def BCS(self, data): - return "BCS %s" % hex(data) + def BCS(self, data, address): + return "BCS %s" % hex(address) - def BEQ(self, data): - return "BEQ %s" % hex(data) + def BEQ(self, data, address): + return "BEQ %s" % hex(address) - def BIT(self, data): + def BIT(self, data, address): return "BIT %s" % hex(data) - def BMI(self, data): - return "BMI %s" % hex(data) + def BMI(self, data, address): + return "BMI %s" % hex(address) - def BNE(self, data): - return "BNE %s" % hex(data) + def BNE(self, data, address): + return "BNE %s" % hex(address) - def BPL(self, data): + def BPL(self, data, address): return "BPL %s" % hex(data) - def BRK(self, data): + def BRK(self, data, address): return "BRK" - def BVC(self, data): - return "BVC %s" % hex(data) + def BVC(self, data, address): + return "BVC %s" % hex(address) - def BVS(self, data): - return "BVS %s" % hex(data) + def BVS(self, data, address): + return "BVS %s" % hex(address) - def CLC(self, data): + def CLC(self, data, address): return "CLC" - def CLD(self, data): + def CLD(self, data, address): return "CLD" - def CLI(self, data): + def CLI(self, data, address): return "CLI" - def CLV(self, data): + def CLV(self, data, address): return "CLV" - def CMP(self, data): + def CMP(self, data, address): return "CMP %s" % hex(data) - def CPX(self, data): + def CPX(self, data, address): return "CPX %s" % hex(data) - def CPY(self, data): + def CPY(self, data, address): return "CPY %s" % hex(data) - def DEC(self, data): + def DEC(self, data, address): return "DEC %s" % hex(data) - def DEX(self, data): + def DEX(self, data, address): return "DEX" - def DEY(self, data): + def DEY(self, data, address): return "DEY" - def EOR(self, data): + def EOR(self, data, address): return "EOR %s" % hex(data) - def INC(self, data): + def INC(self, data, address): return "INC %s" % hex(data) - def INX(self, data): + def INX(self, data, address): return "INX" - def INY(self, data): + def INY(self, data, address): return "INY" - def JMP(self, data): - return "JMP %s" % hex(data) + def JMP(self, data, address): + return "JMP %s" % hex(address) - def JSR(self, data): - return "JSR %s" % hex(data) + def JSR(self, data, address): + return "JSR %s" % hex(address) - def LDA(self, data): + def LDA(self, data, address): return "LDA %s" % hex(data) - def LDX(self, data): + def LDX(self, data, address): return "LDX %s" % hex(data) - def LDY(self, data): + def LDY(self, data, address): return "LDY %s" % hex(data) - def LSR(self, data): + def LSR(self, data, address): return "LSR %s" % hex(data) - def NOP(self, data): + def NOP(self, data, address): return "NOP" - def ORA(self, data): + def ORA(self, data, address): return "ORA %s" % hex(data) - def PHA(self, data): + def PHA(self, data, address): return "PHA" - def PHP(self, data): + def PHP(self, data, address): return "PHP" - def PLA(self, data): + def PLA(self, data, address): return "PLA" - def PLP(self, data): + def PLP(self, data, address): return "PLP" - def ROL(self, data): + def ROL(self, data, address): return "ROL %s" % hex(data) - def ROR(self, data): + def ROR(self, data, address): return "ROR %s" % hex(data) - def RTI(self, data): + def RTI(self, data, address): return "RTI" - def RTS(self, data): + def RTS(self, data, address): return "RTS" - def SBC(self, data): + def SBC(self, data, address): return "SBC %s" % hex(data) - def SEC(self, data): + def SEC(self, data, address): return "SEC" - def SED(self, data): + def SED(self, data, address): return "SED" - def SEI(self, data): + def SEI(self, data, address): return "SEI" - def STA(self, data): + def STA(self, data, address): return "STA %s" % hex(data) - def STX(self, data): + def STX(self, data, address): return "STX %s" % hex(data) - def STY(self, data): + def STY(self, data, address): return "STY %s" % hex(data) - def TAX(self, data): + def TAX(self, data, address): return "TAX" - def TAY(self, data): + def TAY(self, data, address): return "TAY" - def TSX(self, data): + def TSX(self, data, address): return "TSX" - def TXA(self, data): + def TXA(self, data, address): return "TXA" - def TXS(self, data): + def TXS(self, data, address): return "TXS" - def TYA(self, data): + def TYA(self, data, address): return "TYA" - def UNDEFINED(self, data): + def UNDEFINED(self, data, address): return "UNDEFINED" + class WritebackDispatcher(object): def A(self, value, location): pass @@ -209,15 +210,16 @@ def PS(self, value, location): def NW(self, value, location): pass + class Disassembler(object): def __init__(self, decoderTablePath): executionDispatcher = ExecutionUnit() - self.memory = Memory.Memory() - self.registers = Registers.RegisterBank() + self.memory = CPU.Memory.Memory() + self.registers = CPU.Registers.RegisterBank() addressDispatcher = AddressDispatch.AddressDispatcher(self.memory, self.registers) writebackDispatcher = WritebackDispatcher() decoder = Decoder.Decoder(decoderTablePath) - self.dispatch = Dispatch.Dispatcher(decoder, addressDispatcher, executionDispatcher, writebackDispatcher, self.memory, self.registers) + self.dispatch = CPU.Dispatch.Dispatcher(decoder, addressDispatcher, executionDispatcher, writebackDispatcher, self.memory, self.registers) class Generator(object): def __init__(self, dispatcher): @@ -234,5 +236,5 @@ def disassemble(self, data): self.memory.map( (0, len(data)), ArrayMemMapper.Mapper(data)) generator = self.Generator(self.dispatch) for decode in generator: - print "%s " % (self.registers.pc), - print ": %s " % (decode) + print( "%s " % (self.registers.pc)), + print(": %s " % (decode)) From 9e8a67a19c2fa91ce742651fe9a2fe2e9ec4aeca Mon Sep 17 00:00:00 2001 From: Charles Ferguson Date: Sat, 25 Nov 2023 04:37:25 +0000 Subject: [PATCH 05/65] Make the executable code executable. The PyBeeb, PyBeebU and test files are now executable under unix systems and given shebang lines. --- DisassembleTest.py | 1 + MemoryTests.py | 2 ++ PyBeeb.py | 1 + PyBeebU.py | 1 + 4 files changed, 5 insertions(+) mode change 100644 => 100755 DisassembleTest.py mode change 100644 => 100755 MemoryTests.py mode change 100644 => 100755 PyBeeb.py mode change 100644 => 100755 PyBeebU.py diff --git a/DisassembleTest.py b/DisassembleTest.py old mode 100644 new mode 100755 index ec29f2b..650c59f --- a/DisassembleTest.py +++ b/DisassembleTest.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python ''' Created on 12 Oct 2011 diff --git a/MemoryTests.py b/MemoryTests.py old mode 100644 new mode 100755 index a236130..1b2e33b --- a/MemoryTests.py +++ b/MemoryTests.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python + import unittest import pybeeb.CPU.Memory diff --git a/PyBeeb.py b/PyBeeb.py old mode 100644 new mode 100755 index db325b8..8e5fadf --- a/PyBeeb.py +++ b/PyBeeb.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python ''' Created on 12 Oct 2011 diff --git a/PyBeebU.py b/PyBeebU.py old mode 100644 new mode 100755 index 2470470..f2eb820 --- a/PyBeebU.py +++ b/PyBeebU.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python ''' Created on 12 Oct 2011 From b24b2cde1bfb15229fe0156798b753a47525fcbf Mon Sep 17 00:00:00 2001 From: Charles Ferguson Date: Sat, 25 Nov 2023 11:43:57 +0000 Subject: [PATCH 06/65] Move execution hooks to just before execution. The execution hook was happening before the start of the decode because there wasn't an easy way to inject after it. This meant that it was not possible to report the instruction length. It might not be a big problem, but it did mean that we couldn't call the hook as easily. We now call the hook with the right details by having a class that inherits from the Dispatcher do the hook calls. --- pybeeb/BBCMicro/System.py | 6 ++-- pybeeb/CPU/Dispatch.py | 35 ++++++++++++++++++--- pybeeb/PyBeebicorn.py | 64 +++++++++++++++++++++++++-------------- 3 files changed, 75 insertions(+), 30 deletions(-) diff --git a/pybeeb/BBCMicro/System.py b/pybeeb/BBCMicro/System.py index 1b644f4..6af241b 100644 --- a/pybeeb/BBCMicro/System.py +++ b/pybeeb/BBCMicro/System.py @@ -3,9 +3,9 @@ @author: Chris ''' -import OS -import PagedROM -import Sheila +from . import OS +from . import PagedROM +from . import Sheila class Beeb(object): def __init__(self, cpu): diff --git a/pybeeb/CPU/Dispatch.py b/pybeeb/CPU/Dispatch.py index a217360..6a9f88c 100644 --- a/pybeeb/CPU/Dispatch.py +++ b/pybeeb/CPU/Dispatch.py @@ -4,7 +4,8 @@ @author: chris.whitworth ''' -class Dispatcher: +class Dispatcher(object): + def __init__(self, decoder, addressDispatcher, executionDispatcher, writebackDispatcher, memory, registers): self.decoder = decoder self.memory = memory @@ -114,14 +115,29 @@ def addressDecode(self, opcode): addressingMode = self.decoder.addressingMode(opcode) return self.addressTable[addressingMode]() - def dispatch(self): - #Decode + def decode(self, pc): + """ + Decode an instruction at a given address. + + @return: Tuple of the (opcode value, instruction name, writeback type, instruction length) + """ opcode = self.memory.readByte(self.registers.pc) instruction = self.decoder.instruction(opcode) writeback = self.decoder.writeback(opcode) - self.registers.nextPC = self.registers.pc + self.decoder.instructionLength(opcode) + return (opcode, instruction, writeback, self.decoder.instructionLength(opcode)) + + def execute(self, pc, length, opcode, instruction, writeback): + """ + Execute a decoded instruction. - #execute + @param pc: address executed from + @param length: length of the opcode + @param opcode: opcode value + @param instruction: decoded instruction name + @param writeback: decoded writeback type + + @return: value which was written + """ data = self.dataDecode(opcode) address = self.addressDecode(opcode) result = self.executionTable[instruction](data, address) @@ -131,6 +147,15 @@ def dispatch(self): self.registers.pc = self.registers.nextPC + def dispatch(self): + # Decode + pc = self.registers.pc + (opcode, instruction, writeback, length) = self.decode(pc) + self.registers.nextPC = pc + length + + # Execute + result = self.execute(pc, length, opcode, instruction, writeback) + return result def reset(self): diff --git a/pybeeb/PyBeebicorn.py b/pybeeb/PyBeebicorn.py index abbdf2c..28d8ba2 100644 --- a/pybeeb/PyBeebicorn.py +++ b/pybeeb/PyBeebicorn.py @@ -65,8 +65,9 @@ def pb_version(): class PbHook(object): - def __init__(self, pb, callback, user_data=None, begin=1, end=0): + def __init__(self, pb, htype, callback, user_data=None, begin=1, end=0): self.pb = pb + self.htype = htype self.callback = callback self.user_data = user_data self.address = begin @@ -81,25 +82,51 @@ def call(self, *args): self.callback(self.pb, *args) +class PbDispatcher(Dispatch.Dispatcher): + """ + Dispatcher which handles execution hooks. + """ + def __init__(self, pb, decoder, addressDispatcher, executionDispatcher, writebackDispatcher, memory, registers): + super(PbDispatcher, self).__init__(decoder, addressDispatcher, executionDispatcher, writebackDispatcher, + memory, registers) + self.pb = pb + + # Execution hooks - when we hit an address in the range we call the hook + self.hook_exec = [] + + def hook_add(self, hook): + self.hook_exec.append(hook) + + def hook_del(self, hook): + self.hook_exec.remove(hook) + + def execute(self, pc, length, opcode, instruction, writeback): + for hook in self.hook_exec: + if pc in hook: + hook.call(pc, length) + if self.pb.executing: + super(PbDispatcher, self).execute(pc, length, opcode, instruction, writeback) + + class Pb(object): insts_filename = os.path.join(os.path.dirname(__file__), 'insts.csv') def __init__(self): # We only support 6502, so there is no architecture or mode flag. - self.mem = Memory.Memory() + self.memory = Memory.Memory() self.reg = Registers.RegisterBank() - addrDispatch = AddressDispatcher.AddressDispatcher(self.mem, self.reg) + addrDispatch = AddressDispatcher.AddressDispatcher(self.memory, self.reg) - execDispatch = ExecutionUnit.ExecutionDispatcher(self.mem,self.reg) - writebackDispatch = Writeback.Dispatcher(self.mem,self.reg) + execDispatch = ExecutionUnit.ExecutionDispatcher(self.memory,self.reg) + writebackDispatch = Writeback.Dispatcher(self.memory,self.reg) decoder = Decoder.Decoder(self.insts_filename) - dispatch = Dispatch.Dispatcher(decoder, addrDispatch, - execDispatch, writebackDispatch, - self.mem, self.reg) + self.dispatch = PbDispatcher(self, decoder, addrDispatch, + execDispatch, writebackDispatch, + self.memory, self.reg) - self.bbc = BBCMicro.System.Beeb(dispatch) + self.bbc = BBCMicro.System.Beeb(self.dispatch) self.executing = False @@ -127,9 +154,6 @@ def write_y(v): PbConstants.PB_6502_REG_PS: (lambda: self.reg.ps(), lambda v: self.reg.setPS(v)), } - # Execution hooks - when we hit an address in the range we call the hook - self.hook_exec = [] - # emulate from @begin, and stop when reaching address @until def emu_start(self, begin, until, count=0): insts = 0 @@ -138,10 +162,6 @@ def emu_start(self, begin, until, count=0): while self.executing and self.reg.pc != until: #print "%s: PC: %s" % (insts, hex(self.reg.pc)) - for hook in self.hook_exec: - if self.reg.pc in hook: - hook.call(self.reg.pc, 1) - self.bbc.tick() insts += 1 if count and insts >= count: @@ -157,7 +177,7 @@ def emu_stop(self): def reg_read(self, reg_id): dispatch = self.reg_dispatch.get(reg_id) if not dispatch: - raise PbError(ERR_ARG) + raise PbError(PbConstants.PB_ERR_ARG) return dispatch[0]() @@ -165,7 +185,7 @@ def reg_read(self, reg_id): def reg_write(self, reg_id, value): dispatch = self.reg_dispatch.get(reg_id) if not dispatch: - raise PbError(ERR_ARG) + raise PbError(PbConstants.PB_ERR_ARG) dispatch[1](value & 0xFF) @@ -178,11 +198,11 @@ def mem_write(self, address, data): self.memory.writeBytes(address, data) def hook_add(self, htype, callback, user_data=None, begin=1, end=0, arg1=0): - hook = PbHook(self, callback, user_data=user_data, begin=begin, end=end) + hook = PbHook(self, htype, callback, user_data=user_data, begin=begin, end=end) if htype & PbConstants.PB_HOOK_CODE: - self.hook_exec.append(hook) + self.dispatch.hook_add(hook) return hook def hook_del(self, hook): - if hook in self.hook_exec: - self.hook_exec.remove(hook) + if hook.htype & PbConstants.PB_HOOK_CODE: + self.dispatch.hook_del(hook) From 005547fc82c3dbb7ee1b7c86c361aab347bb30e3 Mon Sep 17 00:00:00 2001 From: Charles Ferguson Date: Sat, 25 Nov 2023 14:20:59 +0000 Subject: [PATCH 07/65] Fix for BRK not dispatching to the IRQ handler. The last address in the memory map regions would not be supplied - the check for whether the memory was in the mapped object was not allowing for the inclusive end address of the mapping. This meant that the IRQ entry point (which is used by BRK) would be called with the high address byte being returned from the standard memory, which was 0. Instead of calling &DC1C, it was calling &001C. We now check the memory region inclusively. --- pybeeb/CPU/Memory.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pybeeb/CPU/Memory.py b/pybeeb/CPU/Memory.py index e06b4d2..986b45e 100644 --- a/pybeeb/CPU/Memory.py +++ b/pybeeb/CPU/Memory.py @@ -29,10 +29,11 @@ def base(self): return self.range[0] def end(self): + # Note: end is inclusive return self.range[1] def isInMap(self, address): - return True if address >= self.base() and address < self.end() else False + return True if address >= self.base() and address <= self.end() else False MEMORYSIZE = 64 * 1024 def __init__(self): From 472abbbbc17ab77c3b841fd4934c9a9c9eba670b Mon Sep 17 00:00:00 2001 From: Charles Ferguson Date: Sat, 25 Nov 2023 14:28:37 +0000 Subject: [PATCH 08/65] Standardise instruction exceptions. The instruction exceptions are now standarised to use an Exception for the instructions, rather than a BaseException. The undefined instructions are also reported as exceptions now, as well. --- pybeeb/CPU/ExecutionUnit.py | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/pybeeb/CPU/ExecutionUnit.py b/pybeeb/CPU/ExecutionUnit.py index 579cab8..3319e39 100644 --- a/pybeeb/CPU/ExecutionUnit.py +++ b/pybeeb/CPU/ExecutionUnit.py @@ -4,18 +4,22 @@ @author: chris.whitworth ''' -class StackOverflowException(BaseException): +class ExecutionException(Exception): pass -class StackUnderflowException(BaseException): + +class StackOverflowException(ExecutionException): pass -class ExecutionDispatcher(object): - class NotImplementedException(BaseException): - def __init__(self): - self.instr = "" +class StackUnderflowException(ExecutionException): + pass + +class NotImplementedException(ExecutionException): + def __init__(self, opcode): + self.opcode = opcode + super(NotImplementedException, self).__init__("Opcode &%08x is not implemented" % (opcode,)) - def __repr__(self): - "%s is not implemented" + +class ExecutionDispatcher(object): def __init__(self, memory, registers): self.memory = memory @@ -116,7 +120,8 @@ def BRK(self, data, address): self.registers.brk = True self.pushWord(self.registers.pc + 2) self.pushByte(self.registers.ps()) - return self.memory.readWord(0xfffe) + brk_handler = self.memory.readWord(0xfffe) + return brk_handler def BVC(self, data, address): if not self.registers.overflow: @@ -279,7 +284,6 @@ def RTI(self, data, address): self.registers.brk = False return self.pullWord() - def RTS(self, data, address): location = self.pullWord() return location + 1 @@ -350,5 +354,5 @@ def TYA(self, data, address): return result def UNDEFINED(self, data, address): - pass -# raise self.NotImplementedException() + opcode = self.memory.readByte(self.registers.pc) + raise NotImplementedException(opcode) From ef80517bc69d1f45add2755d3d51ad416a11e342 Mon Sep 17 00:00:00 2001 From: Charles Ferguson Date: Sat, 25 Nov 2023 14:31:52 +0000 Subject: [PATCH 09/65] Update Registers to have a useful __repr__. The __repr__ for Registers now includes their values. --- pybeeb/CPU/Registers.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/pybeeb/CPU/Registers.py b/pybeeb/CPU/Registers.py index 71769c6..abcfcb9 100644 --- a/pybeeb/CPU/Registers.py +++ b/pybeeb/CPU/Registers.py @@ -5,6 +5,7 @@ ''' class RegisterBank(object): + def __init__(self): self.pc = 0x0000 self.sp = 0xff @@ -21,6 +22,16 @@ def __init__(self): self.overflow = False self.negative = False + def __repr__(self): + state = [] + state.append('pc: &%04x' % (self.pc,)) + state.append('sp: &%02x' % (self.sp,)) + state.append('a: &%02x' % (self.a,)) + state.append('x: &%02x' % (self.x,)) + state.append('y: &%02x' % (self.y,)) + return "<{}({})>".format(self.__class__.__name__, ', '.join(state)) + + def ps(self): return ( (1 if self.carry else 0) | (2 if self.zero else 0) | @@ -49,8 +60,6 @@ def reset(self): self.setPS(0) def status(self): - - print "%s%s.%s%s%s%s%s" % ( "N" if self.negative else "-", "V" if self.overflow else "-", From 777a57df9d10b396c45456607dc76ea2ab8bd2af Mon Sep 17 00:00:00 2001 From: Charles Ferguson Date: Sat, 25 Nov 2023 14:33:10 +0000 Subject: [PATCH 10/65] Fix for readBytes/writeBytes interface not terminating. The readBytes and writeBytes interfaces hadn't stopped when they reached the end of the requested region because of a failure to account of the end of mapped regions. --- pybeeb/CPU/Memory.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/pybeeb/CPU/Memory.py b/pybeeb/CPU/Memory.py index 986b45e..05b0d14 100644 --- a/pybeeb/CPU/Memory.py +++ b/pybeeb/CPU/Memory.py @@ -25,6 +25,11 @@ def __init__(self, range, callback): self.range = range self.callback = callback + def __repr__(self): + return "<{}(base=&{:04x}, end=&{:04x}, callback={!r})>".format(self.__class__.__name__, + self.base(), self.end(), + self.callback) + def base(self): return self.range[0] @@ -121,7 +126,7 @@ def readBytes(self, address, size): end = map.end() mappedDevice = map.callback base = map.base() - map_data = bytearray([mappedDevice.readByte(offset) for offset in range(address - base, end)]) + map_data = bytearray([mappedDevice.readByte(offset) for offset in range(address - base, end - base)]) data += map_data else: @@ -130,7 +135,7 @@ def readBytes(self, address, size): map = self.getNextMap(address) if map: # there is a following map. - next_start = address - size + next_start = map.base() else: next_start = 0x10000 @@ -150,7 +155,7 @@ def writeBytes(self, address, value): Read multiple bytes into a bytearray / mapped region. """ size = len(value) - if not isinstance(value): + if not isinstance(value, bytearray): value = bytearray(value) if address < 0: @@ -174,7 +179,7 @@ def writeBytes(self, address, value): map = self.getNextMap(address) if map: # there is a following map. - next_start = address - size + next_start = map.base() else: next_start = 0x10000 @@ -188,8 +193,6 @@ def writeBytes(self, address, value): size -= (end - address) address = end - return data - def readSignedByte(self, address): b = self.readByte(address) return unpack("b", chr(b))[0] From deb9acc527ada3909cb0a7869c26c121500b9d9a Mon Sep 17 00:00:00 2001 From: Charles Ferguson Date: Sat, 25 Nov 2023 14:34:14 +0000 Subject: [PATCH 11/65] Fix PyBeebicorn's handling of register writes; hooks can now reset PC. The register writes in the PyBeebicorn interface were always being AND'd with 255, even for the PC. The value stored is checked in each writer function now. The execution hooks are now able to reset the PC value when they are run, preventing the execution of the instruction that was decoded. --- pybeeb/PyBeebicorn.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/pybeeb/PyBeebicorn.py b/pybeeb/PyBeebicorn.py index 28d8ba2..9bf97fe 100644 --- a/pybeeb/PyBeebicorn.py +++ b/pybeeb/PyBeebicorn.py @@ -104,8 +104,12 @@ def execute(self, pc, length, opcode, instruction, writeback): for hook in self.hook_exec: if pc in hook: hook.call(pc, length) + if pc != self.pb.reg.pc: + # They changed the execution location, so we're not running this instruction any more. + return self.pb.reg.pc + if self.pb.executing: - super(PbDispatcher, self).execute(pc, length, opcode, instruction, writeback) + return super(PbDispatcher, self).execute(pc, length, opcode, instruction, writeback) class Pb(object): @@ -131,19 +135,20 @@ def __init__(self): self.executing = False def write_pc(v): - self.reg.pc = v + print("Set PC to &%04x" % (v,)) + self.reg.pc = v & 0xFFFF def write_sp(v): - self.reg.sp = v + self.reg.sp = v & 0xFF def write_a(v): - self.reg.a = v + self.reg.a = v & 0xFF def write_x(v): - self.reg.x = v + self.reg.x = v & 0xFF def write_y(v): - self.reg.y = v + self.reg.y = v & 0xFF self.reg_dispatch = { PbConstants.PB_6502_REG_PC: (lambda: self.reg.pc, write_pc), @@ -187,7 +192,7 @@ def reg_write(self, reg_id, value): if not dispatch: raise PbError(PbConstants.PB_ERR_ARG) - dispatch[1](value & 0xFF) + dispatch[1](value) # read data from memory def mem_read(self, address, size): From c22fca46c068309f318958a3b1b8aac2a0b0496b Mon Sep 17 00:00:00 2001 From: Charles Ferguson Date: Sat, 25 Nov 2023 14:39:07 +0000 Subject: [PATCH 12/65] Minor clean up to the dispatch handler. The BRK now returns the address to call, and reset has a variable instead of just calling a magic address. --- pybeeb/CPU/Dispatch.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pybeeb/CPU/Dispatch.py b/pybeeb/CPU/Dispatch.py index 6a9f88c..c5f925f 100644 --- a/pybeeb/CPU/Dispatch.py +++ b/pybeeb/CPU/Dispatch.py @@ -146,6 +146,7 @@ def execute(self, pc, length, opcode, instruction, writeback): self.writebackTable[writeback](result, address) self.registers.pc = self.registers.nextPC + return result def dispatch(self): # Decode @@ -160,4 +161,5 @@ def dispatch(self): def reset(self): self.registers.reset() - self.registers.pc = self.memory.readWord(0xfffc) + reset_handler = self.memory.readWord(0xfffc) + self.registers.pc = reset_handler From 718043b504ba0b732a7426e2917f5a6dc0ce96ad Mon Sep 17 00:00:00 2001 From: Charles Ferguson Date: Sat, 25 Nov 2023 14:39:53 +0000 Subject: [PATCH 13/65] Add console handling - RDCH is able to work. The RDCH entry point is replaced by a key reader from the console. This uses the console code that I wrote for RISC OS Pyromaniac, modified to be independant on Pyro. This allows the RDCH entry point to be modified to handle the key input. It's not great because we lose *Exec handling, but since we don't have a filesystem or any other interfaces, that's not a big deal right now. --- PyBeebU.py | 32 +++- console.py | 477 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 504 insertions(+), 5 deletions(-) create mode 100644 console.py diff --git a/PyBeebU.py b/PyBeebU.py index f2eb820..aea815f 100755 --- a/PyBeebU.py +++ b/PyBeebU.py @@ -8,6 +8,7 @@ import sys from pybeeb.PyBeebicorn import Pb, PbError, PbConstants +from console import Console class BBC(object): @@ -29,13 +30,34 @@ def go(self, syscalls): self.pb.hook_del(hook) -def OS_WRCH(pb, address, size, user_data): sys.stdout.write(chr(pb.reg_read(PbConstants.PB_6502_REG_A))) -def OS_RDCH(pb, address, size, user_data): print "OS_RDCH" # Could inject keypresses here maybe? - if __name__ == "__main__": OS_WRCH_LOC = 0xe0a4 OS_RDCH_LOC = 0xdec5 + + console = Console() + + def OS_WRCH(pb, address, size, user_data): + sys.stdout.write(chr(pb.reg_read(PbConstants.PB_6502_REG_A))) + + def OS_RDCH(pb, address, size, user_data): + # See: https://mdfs.net/Docs/Comp/BBC/OS1-20/DC1C + #print "OS_RDCH" # Could inject keypresses here maybe? + ch = console.getch() + pb.reg_write(PbConstants.PB_6502_REG_A, ord(ch)) + pb.reg_write(PbConstants.PB_6502_REG_PC, 0xDF0B) # RTS instruction + + def trace(pb, address, size, user_data): + data = pb.mem_read(address, size) + execcode = ' '.join('%02x' % (b,) for b in data) + print("&%04x: %s" % (address, execcode)) + + bbc = BBC() + #bbc.pb.hook_add(PbConstants.PB_HOOK_CODE, trace, begin=0xDEC5, end=0xDF10) + syscalls = { OS_WRCH_LOC : OS_WRCH, OS_RDCH_LOC : OS_RDCH } - bbc = BBC() - bbc.go(syscalls) + try: + console.terminal_init() + bbc.go(syscalls) + finally: + console.terminal_reset() diff --git a/console.py b/console.py new file mode 100644 index 0000000..d6d1594 --- /dev/null +++ b/console.py @@ -0,0 +1,477 @@ +""" +Console controlling operations for POSIX systems +""" + +import array +import errno +import fcntl +import os +import select +import sys +import termios +import time +import tty + + +class ConsoleBase(object): + """ + Console management from the host enviroment. + """ + + # FIXME: It's arguable that the console input should run continually in a thread + # and push keys into buffers. + + def __init__(self): + super(ConsoleBase, self).__init__() + self.inited = False + self.cooked_newlines = True + self.output = sys.stdout + + def terminal_init(self): + self.inited = True + + def terminal_reset(self): + self.inited = False + + def encode(self, uni): + """ + Encode a UTF-8 sequence into the 8-bit form + """ + return uni.encode('latin-1') + + def write(self, message): + """ + Write a message to the actual console. + """ + #sys.stderr.write("<|%r|%r>" % (message, self.output)) + if not self.cooked_newlines: + message = message.replace('\n', '\r\n') + self.output.write(message) + + def writeln(self, message): + self.write(message + '\n') + + def flush(self): + self.output.flush() + + def finalise(self): + if self.__class__ == ConsoleBase: + # We don't want the base class messing with our configuration. + return + + if self.inited: + self.terminal_reset() + + def getch(self, timeout=None): + return None + + def handle_eof(self): + """ + Do whatever you need to when an EOF is received from the host. + + @return: True if we handled it; False if there was nothing done. + """ + return False + + +class ConsoleConfig(object): + flush_output_on_read = True + input_escapes = True + input_escapes_timeout = 0.2 + input_utf8 = True + input_backspace_code = 8 + + +class Console(ConsoleBase): + # Letter sequences have been stripped of the modifier if the modifier was '1'. + # [1A => [A + # ~ sequences have been stripped of the modifier if the modifier was '1'. + # [24;1~ => [24~ + escape_codes = { + # Standard sequences + '[A': '\x8F', # Up + '[B': '\x8E', # Down + '[C': '\x8D', # Right + '[D': '\x8C', # Left + '[F': '\x8B', # End (Copy in RISC OS terms) + '[H': '\x1E', # Home + '[Z': '\x09', # Shift-Tab + + # Application sequences + 'OP': '\x81', # F1 + 'OQ': '\x82', # F2 + 'OR': '\x83', # F3 + 'OS': '\x84', # F4 + 'OH': '\x1E', # Home + 'OF': '\x8B', # End + + # VT sequences + '[1~': '\x1E', # Home (don't know what this should be) + #'[2~': '\x89', # Insert (don't know what this should be) + '[3~': '\x7F', # Delete + '[4~': '\x8B', # End + '[5~': '\x9F', # Page Up + '[6~': '\x9E', # Page Down + '[7~': '\x1E', # Home + '[8~': '\x87', # End + '[11~': '\x81', # F1 + '[12~': '\x82', # F2 + '[13~': '\x83', # F3 + '[14~': '\x84', # F4 + '[15~': '\x85', # F5 + # Note 16 isn't mapped + '[17~': '\x86', # F6 + '[18~': '\x87', # F7 + '[19~': '\x88', # F8 + '[20~': '\x89', # F9 + '[21~': '\xCA', # F10 + # Note 22 isn't mapped + '[23~': '\xCB', # F11 + '[24~': '\xCC', # F12 + + '[25~': '\x80', # Print (don't know what this should be) + + # Shifted keys + '[1;2P': '\x91', # Shift-F1 + '[1;2Q': '\x92', # Shift-F2 + '[1;2R': '\x93', # Shift-F3 + '[1;2S': '\x94', # Shift-F4 + '[15;2~': '\x95', # Shift-F5 + '[17;2~': '\x96', # Shift-F6 + '[18;2~': '\x97', # Shift-F7 + '[19;2~': '\x98', # Shift-F8 + '[20;2~': '\x99', # Shift-F9 + '[21;2~': '\xDA', # Shift-F10 + '[23;2~': '\xDB', # Shift-F11 + '[24;2~': '\xDC', # Shift-F12 + + '[1;2A': '\x9F', # Shift-Up + '[1;2B': '\x9E', # Shift-Down + '[1;2C': '\x9D', # Shift-Right + '[1;2D': '\x9C', # Shift-Left + '[1;2F': '\x9B', # Shift-End (Copy in RISC OS terms) + '[1;2H': '\x1E', # Shift-Home + + # Ctrled keys + '[1;5H': '\x1E', # Ctrl-Home + '[1;5F': '\xAB', # Ctrl-End (Copy in RISC OS terms) + } + + def __init__(self): + super(Console, self).__init__() + self.fd = None + self.is_tty = False + self.is_dead = False + self.old_settings = None + self.intbuf = array.array('i', [0]) + self.config = ConsoleConfig() + self.original_stdout = sys.__stdout__ + + # ANSI Escape handling + self.in_utf8_sequence = [] + self.in_escape_sequence = [] + self.in_utf8 = False + self.in_escape = None + + self.debug_inputescapes = False + self.debug_inpututf8 = False + + def get_fd(self): + try: + return sys.stdin.fileno() + except AttributeError: + return None + + def get_isatty(self): + try: + return sys.stdin.isatty() + except AttributeError: + return False + + def terminal_init(self): + if not self.is_dead: + self.fd = self.get_fd() + self.is_tty = self.get_isatty() + + if self.is_tty: + try: + # Preserve old settings + self.old_settings = termios.tcgetattr(self.fd) + + # Set up our requirements + tty.setraw(self.fd, termios.TCSANOW) + new_settings = termios.tcgetattr(self.fd) + + # Output post processing (LF => CR, LF mostly) only if requested + if self.cooked_newlines: + new_settings[1] = new_settings[1] | termios.OPOST | termios.ONLCR + + # Allow interrupt signals + new_settings[3] = new_settings[3] | termios.ISIG + + # Allow a single byte to be read + new_settings[6][termios.VMIN] = '\x01' + new_settings[6][termios.VTIME] = '\x00' + + termios.tcsetattr(self.fd, termios.TCSANOW, new_settings) + except termios.error as exc: + if exc.args[0] == errno.EIO: + self.is_dead = True + self.is_tty = False + else: + raise + if not self.cooked_newlines: + sys.stdout = self + + super(Console, self).terminal_init() + + def terminal_reset(self): + if self.is_tty: + termios.tcsetattr(self.fd, termios.TCSADRAIN, self.old_settings) + if not self.cooked_newlines: + sys.stdout = self.original_stdout + super(Console, self).terminal_reset() + + def parse_utf8(self, seq): + """ + Parse from a UTF-8 sequence into a sequence that we can insert literally. + """ + seq = ''.join(seq) + # Decode the sequence from UTF-8 + decoded = seq.decode('utf-8', 'replace') + if self.debug_inpututf8: + print("Input UTF-8: Sequence %r => %r" % (seq, decoded)) + + # Encode the sequence into the current alphabet + rostr = self.encode(decoded) + if len(rostr) == 1: + return ('\x00', rostr) + else: + acc = [] + for c in rostr: + acc.extend(('\x00', c)) + return acc + + def parse_escape(self, seq): + if len(seq) == 0 or (len(seq) == 1 and seq[0] == '\x1b'): + # Literal escape key! + # FIXME: Should we set the escape flags here too? + return '\x1b' + + if seq[0] == '[': + code = seq[-1] + if (code >= 'A' and code <= 'Z') or (code >= 'a' and code <= 'z'): + # letter codes might have numbers preceding them for modifiers. + # a modifier of 1 means 'no modifier', so we can strip it + if len(seq) == 3 and seq[1] == '1': + # Reduce it to the un-modifier version so our dictionary is simpler + seq = ['[', code] + elif code == '~': + # The [;~ sequence can also have a modifier of 1, + # so we simplify this as well. + if len(seq) > 3 and seq[-3] == ';' and seq[-2] == '1': + seq = seq[:-3] + seq.append('~') + # FIXME: The modifier might be +1 for Shift, +2 for Alt, +4 for Ctrl + + seq = ''.join(seq) + value = self.escape_codes.get(seq, None) + if self.debug_inputescapes: + if value: + print("Input escape: Sequence %r => %r" % (seq, value)) + else: + print("Input escape: Sequence %r not recognised" % (seq,)) + return value + + def getch(self, timeout=None): + # Ensure that if they gave us a prompt or line buffered content, it's actually been output + if self.config.flush_output_on_read: + self.flush() + + # Enable this option if you're trying to debug the underlying input system without + # the escape and UTF-8 handling getting in the way. + if False: + return self.int_getch(timeout=timeout) + + if not self.in_escape and not self.in_utf8: + now = time.time() + ch = self.int_getch(timeout=timeout) + if ch == '\x7F': + ch = chr(self.config.input_backspace_code) + if ch == '\x1b' and self.config.input_escapes: + # This is an escape character, so we're starting a sequence + self.in_escape = time.time() + self.in_escape_sequence = [] + # Work out how much more time we have left until the user's request times out + timeout -= time.time() - now + elif ch >= '\x80' and self.config.input_utf8: + # Likely to be the start of a UTF-8 sequence. + if ch >= '\xc0' and ch <= '\xf7': + # Is a UTF-8 sequence start + self.in_utf8_sequence = [ch] + if ch >= '\xf0': + self.in_utf8 = 4 + elif ch >= '\xe0': + self.in_utf8 = 3 + else: + self.in_utf8 = 2 + else: + # It's not a valid introducing character; so treat it literally + if self.debug_inpututf8: + print("Input UTF-8: Invalid introducer %r" % (ch,)) + return (0, ch) + else: + return ch + + if self.in_escape: + # We know we're in an escape sequence, and we have timeout seconds left. + while timeout > 0 and self.in_escape: + now = time.time() + ch = self.int_getch(timeout=timeout) + if ch is None: + break + # Escapes end with a ~, A-Z, a-z (or a timeout) + + self.in_escape_sequence.append(ch) + # In 'application ' mode, some sequences are sent as SS3 followed by a sequence + # SS3 => O followed by any character. + if self.in_escape_sequence[0] == 'O': + if len(self.in_escape_sequence) == 2: + # SS3 only applies to the next character. + self.in_escape = False + break + else: + if (ch >= 'A' and ch <= 'Z') or (ch >= 'a' and ch <= 'z') or ch == '~': + # This is the end of a sequence + self.in_escape = False + break + + if len(self.in_escape_sequence) == 1 and ch != '[': + # This is an sequence + self.in_escape = False + break + + # Work out how much more time we have left until the user's request times out + timeout -= time.time() - now + + if self.in_escape and time.time() > self.in_escape + self.config.input_escapes_timeout: + self.in_escape = False + + if not self.in_escape: + # Decode the escape sequence + return self.parse_escape(self.in_escape_sequence) + + else: + # We're in a UTF-8 sequence, so we handle this in a similar way but with + # different terminal conditions + while timeout > 0 and self.in_utf8: + now = time.time() + ch = self.int_getch(timeout=timeout) + if ch is None: + return None + if ch < '\x80' or ch >= '\xc0': + # This is not a character that should be in the UTF-8 sequence - it's + # broken UTF-8. + if self.debug_inpututf8: + print("Input UTF-8: Invalid sequence %r + %r" % (self.in_utf8_sequence, ch)) + + # FIXME: Configurable way to handle this? + acc = ''.join(self.in_utf8_sequence) + # FIXME: Discard the characters if wanted, or encode? + if ch < '\x80': + # The excess is a plain character + # FIXME: Note that this doesn't handle the excess character being + # an escape (!) + if acc: + acc += ch + self.in_utf8 = False + else: + # The excess is the start of another UTF-8 sequence, so we + # start another sequence + self.in_utf8_sequence = [ch] + if ch >= '\xf0': + self.in_utf8 = 4 + elif ch >= '\xe0': + self.in_utf8 = 3 + else: + self.in_utf8 = 2 + return acc + + self.in_utf8_sequence.append(ch) + if len(self.in_utf8_sequence) == self.in_utf8: + # We've reached the end of the sequence + self.in_utf8 = False + return self.parse_utf8(self.in_utf8_sequence) + + # Work out how much more time we have left until the user's request times out + timeout -= time.time() - now + + return None + + def is_pending(self, timeout=None): + input_pending = False + + # First check if there are bytes still to read + try: + fcntl.ioctl(self.fd, termios.FIONREAD, self.intbuf) + if self.intbuf[0] > 0: + input_pending = True + except IOError: + # If the device doesn't support FIONREAD, we roll on to the select + pass + + if not input_pending: + # And check for new bytes (within the timeout) + try: + r, w, x = select.select([sys.stdin], [], [], timeout) + if r: + input_pending = True + except select.error as exc: + if exc[0] == errno.EINTR: + return False + else: + raise + + return input_pending + + def int_getch(self, timeout=None): + ch = None + if timeout is not None: + before = time.time() + if self.is_pending(timeout): + if self.is_tty: + # Ensures that we avoid Pythons greedy read in the sys.stdin file handle + # which would otherwise consume more characters, preventing the select + # from being aware that the characters are present. + try: + ch = os.read(self.fd, 1) + except OSError as exc: + # Interrupted system call happens in cases like ctrl-z being pressed. + if exc.errno != errno.EINTR: + raise + ch = None + else: + ch = sys.stdin.read(1) + if ch == '': + if not self.handle_eof(): + # We didn't do anything, but the handle reported EOF. + # We're just going to wait for the timeout period, because otherwise + # we'll just busy wait. + took = time.time() - before + + # For reasons that are unclear, when run under gitlab-runner under MacOS, the + # sleep time here is 5x longer than that we expect, which causes ticks to be + # missed. It is not clear why this happens. However, sleeping smaller fractions + # of the time requested and then waiting until the timeout has expired seems to + # be the only sensible way to deal with this. + while time.time() < before + timeout: + # Sleep in smaller chunks than the requested, so that we don't overrun the + # timeout point by much. + time.sleep(max(timeout - took, 0) / 10) + + ch = None + + else: + ch = sys.stdin.read(1) + + return ch From 77cbeb6b26a007bcc10db9731846080fca62da80 Mon Sep 17 00:00:00 2001 From: Charles Ferguson Date: Sat, 25 Nov 2023 15:45:35 +0000 Subject: [PATCH 14/65] Fix for timeout being None not being handled. The timeout value of None means 'wait forever', but it wasn't actually working because it had never been tested. We now check this more carefully. --- console.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/console.py b/console.py index d6d1594..74f7d3a 100644 --- a/console.py +++ b/console.py @@ -303,7 +303,8 @@ def getch(self, timeout=None): self.in_escape = time.time() self.in_escape_sequence = [] # Work out how much more time we have left until the user's request times out - timeout -= time.time() - now + if timeout is not None: + timeout -= time.time() - now elif ch >= '\x80' and self.config.input_utf8: # Likely to be the start of a UTF-8 sequence. if ch >= '\xc0' and ch <= '\xf7': @@ -325,9 +326,9 @@ def getch(self, timeout=None): if self.in_escape: # We know we're in an escape sequence, and we have timeout seconds left. - while timeout > 0 and self.in_escape: + while (timeout is None or timeout > 0) and self.in_escape: now = time.time() - ch = self.int_getch(timeout=timeout) + ch = self.int_getch(timeout=timeout if timeout > self.config.input_escapes_timeout else self.config.input_escapes_timeout) if ch is None: break # Escapes end with a ~, A-Z, a-z (or a timeout) @@ -352,7 +353,8 @@ def getch(self, timeout=None): break # Work out how much more time we have left until the user's request times out - timeout -= time.time() - now + if timeout is not None: + timeout -= time.time() - now if self.in_escape and time.time() > self.in_escape + self.config.input_escapes_timeout: self.in_escape = False @@ -453,7 +455,7 @@ def int_getch(self, timeout=None): else: ch = sys.stdin.read(1) if ch == '': - if not self.handle_eof(): + if not self.handle_eof() and timeout is not None: # We didn't do anything, but the handle reported EOF. # We're just going to wait for the timeout period, because otherwise # we'll just busy wait. From c4bf2e6d94f757313ae28a6413945fcfc9f64a3e Mon Sep 17 00:00:00 2001 From: Charles Ferguson Date: Sat, 25 Nov 2023 15:46:27 +0000 Subject: [PATCH 15/65] Removed stray debug in PyBeebicorn. A debug had been left in the PyBeebicorn interface when the PC was set. --- pybeeb/PyBeebicorn.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pybeeb/PyBeebicorn.py b/pybeeb/PyBeebicorn.py index 9bf97fe..8beef27 100644 --- a/pybeeb/PyBeebicorn.py +++ b/pybeeb/PyBeebicorn.py @@ -135,7 +135,7 @@ def __init__(self): self.executing = False def write_pc(v): - print("Set PC to &%04x" % (v,)) + #print("Set PC to &%04x" % (v,)) self.reg.pc = v & 0xFFFF def write_sp(v): From f66c4060c1dd8621a5030b0bb1c290881bc8606a Mon Sep 17 00:00:00 2001 From: Charles Ferguson Date: Sat, 25 Nov 2023 15:47:09 +0000 Subject: [PATCH 16/65] Update the PyBeebU to handle lack of input. If there's no input, we could return None. This might happen if there had been input but no characters were actually read, or the timeout occurred. --- PyBeebU.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/PyBeebU.py b/PyBeebU.py index aea815f..e9d8d43 100755 --- a/PyBeebU.py +++ b/PyBeebU.py @@ -42,7 +42,10 @@ def OS_WRCH(pb, address, size, user_data): def OS_RDCH(pb, address, size, user_data): # See: https://mdfs.net/Docs/Comp/BBC/OS1-20/DC1C #print "OS_RDCH" # Could inject keypresses here maybe? - ch = console.getch() + while True: + ch = console.getch() + if ch is not None: + break pb.reg_write(PbConstants.PB_6502_REG_A, ord(ch)) pb.reg_write(PbConstants.PB_6502_REG_PC, 0xDF0B) # RTS instruction From d89e47305a3c01c0023289a6a951ac7d4d5b05c4 Mon Sep 17 00:00:00 2001 From: Charles Ferguson Date: Sat, 25 Nov 2023 15:53:47 +0000 Subject: [PATCH 17/65] Update the handling of backspace to delete characters. We can now delete characters in the character input handler, and they will be output properly. --- PyBeebU.py | 6 +++++- console.py | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/PyBeebU.py b/PyBeebU.py index e9d8d43..057447a 100755 --- a/PyBeebU.py +++ b/PyBeebU.py @@ -37,7 +37,11 @@ def go(self, syscalls): console = Console() def OS_WRCH(pb, address, size, user_data): - sys.stdout.write(chr(pb.reg_read(PbConstants.PB_6502_REG_A))) + c = pb.reg_read(PbConstants.PB_6502_REG_A) + if c == 127: + sys.stdout.write('\x08 \x08') + else: + sys.stdout.write(chr(c)) def OS_RDCH(pb, address, size, user_data): # See: https://mdfs.net/Docs/Comp/BBC/OS1-20/DC1C diff --git a/console.py b/console.py index 74f7d3a..6fb2397 100644 --- a/console.py +++ b/console.py @@ -79,7 +79,7 @@ class ConsoleConfig(object): input_escapes = True input_escapes_timeout = 0.2 input_utf8 = True - input_backspace_code = 8 + input_backspace_code = 127 class Console(ConsoleBase): From 96586627a91372fd40101341186eef9a3d91a6d9 Mon Sep 17 00:00:00 2001 From: Charles Ferguson Date: Sat, 25 Nov 2023 23:25:56 +0000 Subject: [PATCH 18/65] Add support for memory access hooks. The memory access hooks allow us to report when reads or writes happen to memory. They may be problematic at the moment as the store operations appear to read the values from the memory as well, before they then go and store to the locations. --- PyBeebU.py | 7 +++ pybeeb/PyBeebicorn.py | 128 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 134 insertions(+), 1 deletion(-) diff --git a/PyBeebU.py b/PyBeebU.py index 057447a..ee7d4de 100755 --- a/PyBeebU.py +++ b/PyBeebU.py @@ -58,8 +58,15 @@ def trace(pb, address, size, user_data): execcode = ' '.join('%02x' % (b,) for b in data) print("&%04x: %s" % (address, execcode)) + def mem_hook(pb, access, address, size, value, user_data): + print("Access %s of &%04x, size %-3i from &%04x" % ('READ' if access == PbConstants.PB_MEM_READ else 'WRITE', + address, size, + pb.reg_read(PbConstants.PB_6502_REG_PC))) + bbc = BBC() #bbc.pb.hook_add(PbConstants.PB_HOOK_CODE, trace, begin=0xDEC5, end=0xDF10) + #bbc.pb.hook_add(PbConstants.PB_HOOK_MEM_READ | PbConstants.PB_HOOK_MEM_WRITE, mem_hook, begin=0xe00, end=0xe01) + #bbc.pb.hook_add(PbConstants.PB_HOOK_MEM_READ | PbConstants.PB_HOOK_MEM_WRITE, mem_hook, begin=0xe00, end=0x7c00) syscalls = { OS_WRCH_LOC : OS_WRCH, OS_RDCH_LOC : OS_RDCH } diff --git a/pybeeb/PyBeebicorn.py b/pybeeb/PyBeebicorn.py index 8beef27..ad2db82 100644 --- a/pybeeb/PyBeebicorn.py +++ b/pybeeb/PyBeebicorn.py @@ -72,6 +72,7 @@ def __init__(self, pb, htype, callback, user_data=None, begin=1, end=0): self.user_data = user_data self.address = begin self.end = end + self.size = end - begin def __contains__(self, value): return value >= self.address and value < self.end @@ -112,12 +113,133 @@ def execute(self, pc, length, opcode, instruction, writeback): return super(PbDispatcher, self).execute(pc, length, opcode, instruction, writeback) +class PbMemory(Memory.Memory): + + def __init__(self, pb): + super(PbMemory, self).__init__() + self.pb = pb + # We keep a list of the registered hooks, which are ordered. + # We also keep a list of the hooks keyed by address in the 'hook_simple_*' + # dictionary. These will be used if all the hooks that are registered are + # a single byte long, and none of them use the same address. + # This is likely to be the most common case, and using a dictionary + # we can avoid a more lengthy lookup by searching a list. + self.hook_read = [] + self.hook_simple_read = {} + self.hook_write = [] + self.hook_simple_write = {} + + def hook_add(self, hook): + if hook.htype & PbConstants.PB_HOOK_MEM_READ: + if not self.hook_read or self.hook_simple_read: + # This is the first hook, or there are simple hooks present, so we + # can apply simple hooks. + if hook.size == 1 and not self.hook_simple_read.get(hook.address): + # This is a simple hook, and there's no other hook in the address + self.hook_simple_read[hook.address] = hook + else: + # This is not a simple hook (or another hook at the address exists) + # and there exist simple hooks, so clear them. We'll revert to slow + # hooks. + self.hook_simple_read = {} + self.hook_read.append(hook) + + if hook.htype & PbConstants.PB_HOOK_MEM_WRITE: + if not self.hook_write or self.hook_simple_write: + # This is the first hook, or there are simple hooks present, so we + # can apply simple hooks. + if hook.size == 1 and not self.hook_simple_write.get(hook.address): + # This is a simple hook, and there's no other hook in the address + self.hook_simple_write[hook.address] = hook + else: + # This is not a simple hook (or another hook at the address exists) + # and there exist simple hooks, so clear them. We'll revert to slow + # hooks. + self.hook_simple_write = {} + self.hook_write.append(hook) + + def hook_del(self, hook): + if hook in self.hook_read: + self.hook_read.remove(hook) + if hook.address in self.hook_simple_read: + del self.hook_simple_read[hook.address] + if hook in self.hook_write: + self.hook_write.remove(hook) + if hook.address in self.hook_simple_write: + del self.hook_simple_write[hook.address] + + def readByte(self, address, skip_hook=False): + # Dispatch any hooks for this byte + if not skip_hook and self.hook_read: + if self.hook_simple_read: + hook = self.hook_simple_read.get(address, None) + if hook: + hook.call(PbConstants.PB_MEM_READ, address, 1, 0) + else: + # There's no simple hooks present, but there are hooks, + # so we need to process them + for hook in self.hook_read: + if address in hook: + hook.call(PbConstants.PB_MEM_READ, address, 1, 0) + + return super(PbMemory, self).readByte(address) + + def writeByte(self, address, value, skip_hook=False): + # Dispatch any hooks for this byte + if not skip_hook and self.hook_write: + if self.hook_simple_write: + hook = self.hook_simple_write.get(address, None) + if hook: + hook.call(PbConstants.PB_MEM_WRITE, address, 1, value) + else: + # There's no simple hooks present, but there are hooks, + # so we need to process them + for hook in self.hook_write: + if address in hook: + hook.call(PbConstants.PB_MEM_WRITE, address, 1, value) + + super(PbMemory, self).writeByte(address, value) + + def readBytes(self, address, size, skip_hook=False): + """ + Read multiple bytes into a bytearray / mapped region. + """ + + # Dispatch any hooks for this range + if not skip_hook: + for hook in self.hook_read: + if (address, size) in hook: + # Report only the region of the read that is in the hook + bound_address = max(address, min(hook.address, address + size)) + bound_end = min(address + size, max(hook.end, address + size)) + hook.call(PbConstants.PB_MEM_READ, bound_address, bound_end - bound_address, 0) + + return super(PbMemory, self).readBytes(address, size) + + def writeBytes(self, address, value, skip_hook=False): + """ + Read multiple bytes into a bytearray / mapped region. + """ + # Dispatch any hooks for this range + if not skip_hook: + size = len(value) + for hook in self.hook_write: + if (address, size) in hook: + # Report only the region of the write that is in the hook + bound_address = max(address, min(hook.address, address + size)) + bound_end = min(address + size, max(hook.end, address + size)) + bound_value = value[bound_address - address:bound_end - address] + hook.call(PbConstants.PB_MEM_READ, bound_address, bound_end - bound_address, bound_value) + + super(PbMemory, self).writeBytes(address, value) + + class Pb(object): insts_filename = os.path.join(os.path.dirname(__file__), 'insts.csv') def __init__(self): # We only support 6502, so there is no architecture or mode flag. - self.memory = Memory.Memory() + self.memory = PbMemory(self) self.reg = Registers.RegisterBank() addrDispatch = AddressDispatcher.AddressDispatcher(self.memory, self.reg) @@ -206,8 +328,12 @@ def hook_add(self, htype, callback, user_data=None, begin=1, end=0, arg1=0): hook = PbHook(self, htype, callback, user_data=user_data, begin=begin, end=end) if htype & PbConstants.PB_HOOK_CODE: self.dispatch.hook_add(hook) + if htype & (PbConstants.PB_HOOK_MEM_READ | PbConstants.PB_HOOK_MEM_WRITE): + self.memory.hook_add(hook) return hook def hook_del(self, hook): if hook.htype & PbConstants.PB_HOOK_CODE: self.dispatch.hook_del(hook) + if hook.htype & (PbConstants.PB_HOOK_MEM_READ | PbConstants.PB_HOOK_MEM_WRITE): + self.memory.hook_del(hook) From 00184d8a3944febcff5cd9c3dc44b48e9aa8a68c Mon Sep 17 00:00:00 2001 From: Charles Ferguson Date: Sun, 26 Nov 2023 09:20:02 +0000 Subject: [PATCH 19/65] Add support for Escape in the RDCH function. The RDCH function was not reading the escape key properly, because we weren't setting the C flag. It also appears that unless you set the error condition in zero-page, the system won't report the error properly. --- PyBeebU.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/PyBeebU.py b/PyBeebU.py index ee7d4de..eb726f8 100755 --- a/PyBeebU.py +++ b/PyBeebU.py @@ -50,7 +50,18 @@ def OS_RDCH(pb, address, size, user_data): ch = console.getch() if ch is not None: break - pb.reg_write(PbConstants.PB_6502_REG_A, ord(ch)) + ch = ord(ch) + ps = pb.reg_read(PbConstants.PB_6502_REG_PS) + if ch == 27: + ps |= PbConstants.PB_6502_FLAG_CARRY + + # Bit of a hack as we don't have interrupts + # Set the escape flag + pb.mem_write(0xFF, bytearray([0x80])) + else: + ps &= ~PbConstants.PB_6502_FLAG_CARRY + pb.reg_write(PbConstants.PB_6502_REG_PS, ps) + pb.reg_write(PbConstants.PB_6502_REG_A, ch) pb.reg_write(PbConstants.PB_6502_REG_PC, 0xDF0B) # RTS instruction def trace(pb, address, size, user_data): From 7154399c4c82c4132d7415908631ee20b10d0609 Mon Sep 17 00:00:00 2001 From: Charles Ferguson Date: Tue, 28 Nov 2023 00:14:11 +0000 Subject: [PATCH 20/65] Update the console.py module with full version from Pyromaniac. I had originally cut down the console.py to be a limited, POSIX only, version of the console.py implementation. However, there's no reason why this cannot be used on Windows so I may as well include the Windows version. It should work reasonably well, but it's not as polished as the POSIX version. --- console.py | 888 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 513 insertions(+), 375 deletions(-) diff --git a/console.py b/console.py index 6fb2397..be90984 100644 --- a/console.py +++ b/console.py @@ -1,16 +1,17 @@ """ -Console controlling operations for POSIX systems +Console input and output management. +This module needs to manage the interface to the host system using whatever interfaces +are present. Because this is highly dependant on the host system, we have different +implementations for the POSIX style systems (macOS and Linux), and Windows. No +RISC OS implementation is present - it needs more work to make that happen. """ -import array import errno -import fcntl import os -import select +import Queue import sys -import termios +import threading import time -import tty class ConsoleBase(object): @@ -82,314 +83,242 @@ class ConsoleConfig(object): input_backspace_code = 127 -class Console(ConsoleBase): - # Letter sequences have been stripped of the modifier if the modifier was '1'. - # [1A => [A - # ~ sequences have been stripped of the modifier if the modifier was '1'. - # [24;1~ => [24~ - escape_codes = { - # Standard sequences - '[A': '\x8F', # Up - '[B': '\x8E', # Down - '[C': '\x8D', # Right - '[D': '\x8C', # Left - '[F': '\x8B', # End (Copy in RISC OS terms) - '[H': '\x1E', # Home - '[Z': '\x09', # Shift-Tab - - # Application sequences - 'OP': '\x81', # F1 - 'OQ': '\x82', # F2 - 'OR': '\x83', # F3 - 'OS': '\x84', # F4 - 'OH': '\x1E', # Home - 'OF': '\x8B', # End - - # VT sequences - '[1~': '\x1E', # Home (don't know what this should be) - #'[2~': '\x89', # Insert (don't know what this should be) - '[3~': '\x7F', # Delete - '[4~': '\x8B', # End - '[5~': '\x9F', # Page Up - '[6~': '\x9E', # Page Down - '[7~': '\x1E', # Home - '[8~': '\x87', # End - '[11~': '\x81', # F1 - '[12~': '\x82', # F2 - '[13~': '\x83', # F3 - '[14~': '\x84', # F4 - '[15~': '\x85', # F5 - # Note 16 isn't mapped - '[17~': '\x86', # F6 - '[18~': '\x87', # F7 - '[19~': '\x88', # F8 - '[20~': '\x89', # F9 - '[21~': '\xCA', # F10 - # Note 22 isn't mapped - '[23~': '\xCB', # F11 - '[24~': '\xCC', # F12 - - '[25~': '\x80', # Print (don't know what this should be) - - # Shifted keys - '[1;2P': '\x91', # Shift-F1 - '[1;2Q': '\x92', # Shift-F2 - '[1;2R': '\x93', # Shift-F3 - '[1;2S': '\x94', # Shift-F4 - '[15;2~': '\x95', # Shift-F5 - '[17;2~': '\x96', # Shift-F6 - '[18;2~': '\x97', # Shift-F7 - '[19;2~': '\x98', # Shift-F8 - '[20;2~': '\x99', # Shift-F9 - '[21;2~': '\xDA', # Shift-F10 - '[23;2~': '\xDB', # Shift-F11 - '[24;2~': '\xDC', # Shift-F12 - - '[1;2A': '\x9F', # Shift-Up - '[1;2B': '\x9E', # Shift-Down - '[1;2C': '\x9D', # Shift-Right - '[1;2D': '\x9C', # Shift-Left - '[1;2F': '\x9B', # Shift-End (Copy in RISC OS terms) - '[1;2H': '\x1E', # Shift-Home - - # Ctrled keys - '[1;5H': '\x1E', # Ctrl-Home - '[1;5F': '\xAB', # Ctrl-End (Copy in RISC OS terms) - } - - def __init__(self): - super(Console, self).__init__() - self.fd = None - self.is_tty = False - self.is_dead = False - self.old_settings = None - self.intbuf = array.array('i', [0]) - self.config = ConsoleConfig() - self.original_stdout = sys.__stdout__ - - # ANSI Escape handling - self.in_utf8_sequence = [] - self.in_escape_sequence = [] - self.in_utf8 = False - self.in_escape = None - - self.debug_inputescapes = False - self.debug_inpututf8 = False - - def get_fd(self): - try: - return sys.stdin.fileno() - except AttributeError: - return None - - def get_isatty(self): - try: - return sys.stdin.isatty() - except AttributeError: - return False - - def terminal_init(self): - if not self.is_dead: - self.fd = self.get_fd() - self.is_tty = self.get_isatty() - - if self.is_tty: +try: + import array + import fcntl + import select + import termios + import tty + + # We're on a POSIX-like system, so we should be able to use its configuration. + + class Console(ConsoleBase): + # Letter sequences have been stripped of the modifier if the modifier was '1'. + # [1A => [A + # ~ sequences have been stripped of the modifier if the modifier was '1'. + # [24;1~ => [24~ + escape_codes = { + # Standard sequences + '[A': '\x8F', # Up + '[B': '\x8E', # Down + '[C': '\x8D', # Right + '[D': '\x8C', # Left + '[F': '\x8B', # End (Copy in RISC OS terms) + '[H': '\x1E', # Home + '[Z': '\x09', # Shift-Tab + + # Application sequences + 'OP': '\x81', # F1 + 'OQ': '\x82', # F2 + 'OR': '\x83', # F3 + 'OS': '\x84', # F4 + 'OH': '\x1E', # Home + 'OF': '\x8B', # End + + # VT sequences + '[1~': '\x1E', # Home (don't know what this should be) + #'[2~': '\x89', # Insert (don't know what this should be) + '[3~': '\x7F', # Delete + '[4~': '\x8B', # End + '[5~': '\x9F', # Page Up + '[6~': '\x9E', # Page Down + '[7~': '\x1E', # Home + '[8~': '\x87', # End + '[11~': '\x81', # F1 + '[12~': '\x82', # F2 + '[13~': '\x83', # F3 + '[14~': '\x84', # F4 + '[15~': '\x85', # F5 + # Note 16 isn't mapped + '[17~': '\x86', # F6 + '[18~': '\x87', # F7 + '[19~': '\x88', # F8 + '[20~': '\x89', # F9 + '[21~': '\xCA', # F10 + # Note 22 isn't mapped + '[23~': '\xCB', # F11 + '[24~': '\xCC', # F12 + + '[25~': '\x80', # Print (don't know what this should be) + + # Shifted keys + '[1;2P': '\x91', # Shift-F1 + '[1;2Q': '\x92', # Shift-F2 + '[1;2R': '\x93', # Shift-F3 + '[1;2S': '\x94', # Shift-F4 + '[15;2~': '\x95', # Shift-F5 + '[17;2~': '\x96', # Shift-F6 + '[18;2~': '\x97', # Shift-F7 + '[19;2~': '\x98', # Shift-F8 + '[20;2~': '\x99', # Shift-F9 + '[21;2~': '\xDA', # Shift-F10 + '[23;2~': '\xDB', # Shift-F11 + '[24;2~': '\xDC', # Shift-F12 + + '[1;2A': '\x9F', # Shift-Up + '[1;2B': '\x9E', # Shift-Down + '[1;2C': '\x9D', # Shift-Right + '[1;2D': '\x9C', # Shift-Left + '[1;2F': '\x9B', # Shift-End (Copy in RISC OS terms) + '[1;2H': '\x1E', # Shift-Home + + # Ctrled keys + '[1;5H': '\x1E', # Ctrl-Home + '[1;5F': '\xAB', # Ctrl-End (Copy in RISC OS terms) + } + + def __init__(self): + super(Console, self).__init__() + self.fd = None + self.is_tty = False + self.is_dead = False + self.old_settings = None + self.intbuf = array.array('i', [0]) + self.config = ConsoleConfig() + self.original_stdout = sys.__stdout__ + + # ANSI Escape handling + self.in_utf8_sequence = [] + self.in_escape_sequence = [] + self.in_utf8 = False + self.in_escape = None + + self.debug_inputescapes = False + self.debug_inpututf8 = False + + def get_fd(self): try: - # Preserve old settings - self.old_settings = termios.tcgetattr(self.fd) - - # Set up our requirements - tty.setraw(self.fd, termios.TCSANOW) - new_settings = termios.tcgetattr(self.fd) + return sys.stdin.fileno() + except AttributeError: + return None - # Output post processing (LF => CR, LF mostly) only if requested - if self.cooked_newlines: - new_settings[1] = new_settings[1] | termios.OPOST | termios.ONLCR - - # Allow interrupt signals - new_settings[3] = new_settings[3] | termios.ISIG - - # Allow a single byte to be read - new_settings[6][termios.VMIN] = '\x01' - new_settings[6][termios.VTIME] = '\x00' - - termios.tcsetattr(self.fd, termios.TCSANOW, new_settings) - except termios.error as exc: - if exc.args[0] == errno.EIO: - self.is_dead = True - self.is_tty = False - else: - raise - if not self.cooked_newlines: - sys.stdout = self - - super(Console, self).terminal_init() - - def terminal_reset(self): - if self.is_tty: - termios.tcsetattr(self.fd, termios.TCSADRAIN, self.old_settings) - if not self.cooked_newlines: - sys.stdout = self.original_stdout - super(Console, self).terminal_reset() - - def parse_utf8(self, seq): - """ - Parse from a UTF-8 sequence into a sequence that we can insert literally. - """ - seq = ''.join(seq) - # Decode the sequence from UTF-8 - decoded = seq.decode('utf-8', 'replace') - if self.debug_inpututf8: - print("Input UTF-8: Sequence %r => %r" % (seq, decoded)) - - # Encode the sequence into the current alphabet - rostr = self.encode(decoded) - if len(rostr) == 1: - return ('\x00', rostr) - else: - acc = [] - for c in rostr: - acc.extend(('\x00', c)) - return acc - - def parse_escape(self, seq): - if len(seq) == 0 or (len(seq) == 1 and seq[0] == '\x1b'): - # Literal escape key! - # FIXME: Should we set the escape flags here too? - return '\x1b' - - if seq[0] == '[': - code = seq[-1] - if (code >= 'A' and code <= 'Z') or (code >= 'a' and code <= 'z'): - # letter codes might have numbers preceding them for modifiers. - # a modifier of 1 means 'no modifier', so we can strip it - if len(seq) == 3 and seq[1] == '1': - # Reduce it to the un-modifier version so our dictionary is simpler - seq = ['[', code] - elif code == '~': - # The [;~ sequence can also have a modifier of 1, - # so we simplify this as well. - if len(seq) > 3 and seq[-3] == ';' and seq[-2] == '1': - seq = seq[:-3] - seq.append('~') - # FIXME: The modifier might be +1 for Shift, +2 for Alt, +4 for Ctrl - - seq = ''.join(seq) - value = self.escape_codes.get(seq, None) - if self.debug_inputescapes: - if value: - print("Input escape: Sequence %r => %r" % (seq, value)) - else: - print("Input escape: Sequence %r not recognised" % (seq,)) - return value - - def getch(self, timeout=None): - # Ensure that if they gave us a prompt or line buffered content, it's actually been output - if self.config.flush_output_on_read: - self.flush() - - # Enable this option if you're trying to debug the underlying input system without - # the escape and UTF-8 handling getting in the way. - if False: - return self.int_getch(timeout=timeout) - - if not self.in_escape and not self.in_utf8: - now = time.time() - ch = self.int_getch(timeout=timeout) - if ch == '\x7F': - ch = chr(self.config.input_backspace_code) - if ch == '\x1b' and self.config.input_escapes: - # This is an escape character, so we're starting a sequence - self.in_escape = time.time() - self.in_escape_sequence = [] - # Work out how much more time we have left until the user's request times out - if timeout is not None: - timeout -= time.time() - now - elif ch >= '\x80' and self.config.input_utf8: - # Likely to be the start of a UTF-8 sequence. - if ch >= '\xc0' and ch <= '\xf7': - # Is a UTF-8 sequence start - self.in_utf8_sequence = [ch] - if ch >= '\xf0': - self.in_utf8 = 4 - elif ch >= '\xe0': - self.in_utf8 = 3 + def get_isatty(self): + try: + return sys.stdin.isatty() + except AttributeError: + return False + + def terminal_init(self): + if not self.is_dead: + self.fd = self.get_fd() + self.is_tty = self.get_isatty() + + if self.is_tty: + try: + # Preserve old settings + self.old_settings = termios.tcgetattr(self.fd) + + # Set up our requirements + tty.setraw(self.fd, termios.TCSANOW) + new_settings = termios.tcgetattr(self.fd) + + # Output post processing (LF => CR, LF mostly) only if requested + if self.cooked_newlines: + new_settings[1] = new_settings[1] | termios.OPOST | termios.ONLCR + + # Allow interrupt signals + new_settings[3] = new_settings[3] | termios.ISIG + + # Allow a single byte to be read + new_settings[6][termios.VMIN] = '\x01' + new_settings[6][termios.VTIME] = '\x00' + + termios.tcsetattr(self.fd, termios.TCSANOW, new_settings) + except termios.error as exc: + if exc.args[0] == errno.EIO: + self.is_dead = True + self.is_tty = False else: - self.in_utf8 = 2 - else: - # It's not a valid introducing character; so treat it literally - if self.debug_inpututf8: - print("Input UTF-8: Invalid introducer %r" % (ch,)) - return (0, ch) + raise + if not self.cooked_newlines: + sys.stdout = self + + super(Console, self).terminal_init() + + def terminal_reset(self): + if self.is_tty: + termios.tcsetattr(self.fd, termios.TCSADRAIN, self.old_settings) + if not self.cooked_newlines: + sys.stdout = self.original_stdout + super(Console, self).terminal_reset() + + def parse_utf8(self, seq): + """ + Parse from a UTF-8 sequence into a sequence that we can insert literally. + """ + seq = ''.join(seq) + # Decode the sequence from UTF-8 + decoded = seq.decode('utf-8', 'replace') + if self.debug_inpututf8: + print("Input UTF-8: Sequence %r => %r" % (seq, decoded)) + + # Encode the sequence into the current alphabet + rostr = self.encode(decoded) + if len(rostr) == 1: + return ('\x00', rostr) else: - return ch - - if self.in_escape: - # We know we're in an escape sequence, and we have timeout seconds left. - while (timeout is None or timeout > 0) and self.in_escape: - now = time.time() - ch = self.int_getch(timeout=timeout if timeout > self.config.input_escapes_timeout else self.config.input_escapes_timeout) - if ch is None: - break - # Escapes end with a ~, A-Z, a-z (or a timeout) - - self.in_escape_sequence.append(ch) - # In 'application ' mode, some sequences are sent as SS3 followed by a sequence - # SS3 => O followed by any character. - if self.in_escape_sequence[0] == 'O': - if len(self.in_escape_sequence) == 2: - # SS3 only applies to the next character. - self.in_escape = False - break + acc = [] + for c in rostr: + acc.extend(('\x00', c)) + return acc + + def parse_escape(self, seq): + if len(seq) == 0 or (len(seq) == 1 and seq[0] == '\x1b'): + # Literal escape key! + # FIXME: Should we set the escape flags here too? + return '\x1b' + + if seq[0] == '[': + code = seq[-1] + if (code >= 'A' and code <= 'Z') or (code >= 'a' and code <= 'z'): + # letter codes might have numbers preceding them for modifiers. + # a modifier of 1 means 'no modifier', so we can strip it + if len(seq) == 3 and seq[1] == '1': + # Reduce it to the un-modifier version so our dictionary is simpler + seq = ['[', code] + elif code == '~': + # The [;~ sequence can also have a modifier of 1, + # so we simplify this as well. + if len(seq) > 3 and seq[-3] == ';' and seq[-2] == '1': + seq = seq[:-3] + seq.append('~') + # FIXME: The modifier might be +1 for Shift, +2 for Alt, +4 for Ctrl + + seq = ''.join(seq) + value = self.escape_codes.get(seq, None) + if self.debug_inputescapes: + if value: + print("Input escape: Sequence %r => %r" % (seq, value)) else: - if (ch >= 'A' and ch <= 'Z') or (ch >= 'a' and ch <= 'z') or ch == '~': - # This is the end of a sequence - self.in_escape = False - break + print("Input escape: Sequence %r not recognised" % (seq,)) + return value - if len(self.in_escape_sequence) == 1 and ch != '[': - # This is an sequence - self.in_escape = False - break + def getch(self, timeout=None): + # Ensure that if they gave us a prompt or line buffered content, it's actually been output + if self.config.flush_output_on_read: + self.flush() - # Work out how much more time we have left until the user's request times out - if timeout is not None: - timeout -= time.time() - now - - if self.in_escape and time.time() > self.in_escape + self.config.input_escapes_timeout: - self.in_escape = False + # Enable this option if you're trying to debug the underlying input system without + # the escape and UTF-8 handling getting in the way. + if False: + return self.int_getch(timeout=timeout) - if not self.in_escape: - # Decode the escape sequence - return self.parse_escape(self.in_escape_sequence) - - else: - # We're in a UTF-8 sequence, so we handle this in a similar way but with - # different terminal conditions - while timeout > 0 and self.in_utf8: + if not self.in_escape and not self.in_utf8: now = time.time() ch = self.int_getch(timeout=timeout) - if ch is None: - return None - if ch < '\x80' or ch >= '\xc0': - # This is not a character that should be in the UTF-8 sequence - it's - # broken UTF-8. - if self.debug_inpututf8: - print("Input UTF-8: Invalid sequence %r + %r" % (self.in_utf8_sequence, ch)) - - # FIXME: Configurable way to handle this? - acc = ''.join(self.in_utf8_sequence) - # FIXME: Discard the characters if wanted, or encode? - if ch < '\x80': - # The excess is a plain character - # FIXME: Note that this doesn't handle the excess character being - # an escape (!) - if acc: - acc += ch - self.in_utf8 = False - else: - # The excess is the start of another UTF-8 sequence, so we - # start another sequence + if ch == '\x7F': + ch = chr(self.config.input_backspace_code) + if ch == '\x1b' and self.config.input_escapes: + # This is an escape character, so we're starting a sequence + self.in_escape = time.time() + self.in_escape_sequence = [] + # Work out how much more time we have left until the user's request times out + if timeout is not None: + timeout -= time.time() - now + elif ch >= '\x80' and self.config.input_utf8: + # Likely to be the start of a UTF-8 sequence. + if ch >= '\xc0' and ch <= '\xf7': + # Is a UTF-8 sequence start self.in_utf8_sequence = [ch] if ch >= '\xf0': self.in_utf8 = 4 @@ -397,83 +326,292 @@ def getch(self, timeout=None): self.in_utf8 = 3 else: self.in_utf8 = 2 - return acc + else: + # It's not a valid introducing character; so treat it literally + if self.debug_inpututf8: + print("Input UTF-8: Invalid introducer %r" % (ch,)) + return (0, ch) + else: + return ch + + if self.in_escape: + # We know we're in an escape sequence, and we have timeout seconds left. + while (timeout is None or timeout > 0) and self.in_escape: + now = time.time() + ch = self.int_getch(timeout=timeout if timeout > self.config.input_escapes_timeout else self.config.input_escapes_timeout) + if ch is None: + break + # Escapes end with a ~, A-Z, a-z (or a timeout) + + self.in_escape_sequence.append(ch) + # In 'application ' mode, some sequences are sent as SS3 followed by a sequence + # SS3 => O followed by any character. + if self.in_escape_sequence[0] == 'O': + if len(self.in_escape_sequence) == 2: + # SS3 only applies to the next character. + self.in_escape = False + break + else: + if (ch >= 'A' and ch <= 'Z') or (ch >= 'a' and ch <= 'z') or ch == '~': + # This is the end of a sequence + self.in_escape = False + break + + if len(self.in_escape_sequence) == 1 and ch != '[': + # This is an sequence + self.in_escape = False + break + + # Work out how much more time we have left until the user's request times out + if timeout is not None: + timeout -= time.time() - now + + if self.in_escape and time.time() > self.in_escape + self.config.input_escapes_timeout: + self.in_escape = False - self.in_utf8_sequence.append(ch) - if len(self.in_utf8_sequence) == self.in_utf8: - # We've reached the end of the sequence - self.in_utf8 = False - return self.parse_utf8(self.in_utf8_sequence) + if not self.in_escape: + # Decode the escape sequence + return self.parse_escape(self.in_escape_sequence) - # Work out how much more time we have left until the user's request times out - timeout -= time.time() - now + else: + # We're in a UTF-8 sequence, so we handle this in a similar way but with + # different terminal conditions + while timeout > 0 and self.in_utf8: + now = time.time() + ch = self.int_getch(timeout=timeout) + if ch is None: + return None + if ch < '\x80' or ch >= '\xc0': + # This is not a character that should be in the UTF-8 sequence - it's + # broken UTF-8. + if self.debug_inpututf8: + print("Input UTF-8: Invalid sequence %r + %r" % (self.in_utf8_sequence, ch)) + + # FIXME: Configurable way to handle this? + acc = ''.join(self.in_utf8_sequence) + # FIXME: Discard the characters if wanted, or encode? + if ch < '\x80': + # The excess is a plain character + # FIXME: Note that this doesn't handle the excess character being + # an escape (!) + if acc: + acc += ch + self.in_utf8 = False + else: + # The excess is the start of another UTF-8 sequence, so we + # start another sequence + self.in_utf8_sequence = [ch] + if ch >= '\xf0': + self.in_utf8 = 4 + elif ch >= '\xe0': + self.in_utf8 = 3 + else: + self.in_utf8 = 2 + return acc + + self.in_utf8_sequence.append(ch) + if len(self.in_utf8_sequence) == self.in_utf8: + # We've reached the end of the sequence + self.in_utf8 = False + return self.parse_utf8(self.in_utf8_sequence) - return None + # Work out how much more time we have left until the user's request times out + timeout -= time.time() - now - def is_pending(self, timeout=None): - input_pending = False + return None - # First check if there are bytes still to read - try: - fcntl.ioctl(self.fd, termios.FIONREAD, self.intbuf) - if self.intbuf[0] > 0: - input_pending = True - except IOError: - # If the device doesn't support FIONREAD, we roll on to the select - pass + def is_pending(self, timeout=None): + input_pending = False - if not input_pending: - # And check for new bytes (within the timeout) + # First check if there are bytes still to read try: - r, w, x = select.select([sys.stdin], [], [], timeout) - if r: + fcntl.ioctl(self.fd, termios.FIONREAD, self.intbuf) + if self.intbuf[0] > 0: input_pending = True - except select.error as exc: - if exc[0] == errno.EINTR: - return False - else: - raise - - return input_pending - - def int_getch(self, timeout=None): - ch = None - if timeout is not None: - before = time.time() - if self.is_pending(timeout): - if self.is_tty: - # Ensures that we avoid Pythons greedy read in the sys.stdin file handle - # which would otherwise consume more characters, preventing the select - # from being aware that the characters are present. - try: - ch = os.read(self.fd, 1) - except OSError as exc: - # Interrupted system call happens in cases like ctrl-z being pressed. - if exc.errno != errno.EINTR: - raise + except IOError: + # If the device doesn't support FIONREAD, we roll on to the select + pass + + if not input_pending: + # And check for new bytes (within the timeout) + try: + r, w, x = select.select([sys.stdin], [], [], timeout) + if r: + input_pending = True + except select.error as exc: + if exc[0] == errno.EINTR: + return False + else: + raise + + return input_pending + + def int_getch(self, timeout=None): + ch = None + if timeout is not None: + before = time.time() + if self.is_pending(timeout): + if self.is_tty: + # Ensures that we avoid Pythons greedy read in the sys.stdin file handle + # which would otherwise consume more characters, preventing the select + # from being aware that the characters are present. + try: + ch = os.read(self.fd, 1) + except OSError as exc: + # Interrupted system call happens in cases like ctrl-z being pressed. + if exc.errno != errno.EINTR: + raise + ch = None + else: + ch = sys.stdin.read(1) + if ch == '': + if not self.handle_eof() and timeout is not None: + # We didn't do anything, but the handle reported EOF. + # We're just going to wait for the timeout period, because otherwise + # we'll just busy wait. + took = time.time() - before + + # For reasons that are unclear, when run under gitlab-runner under MacOS, the + # sleep time here is 5x longer than that we expect, which causes ticks to be + # missed. It is not clear why this happens. However, sleeping smaller fractions + # of the time requested and then waiting until the timeout has expired seems to + # be the only sensible way to deal with this. + while time.time() < before + timeout: + # Sleep in smaller chunks than the requested, so that we don't overrun the + # timeout point by much. + time.sleep(max(timeout - took, 0) / 10) + ch = None - else: - ch = sys.stdin.read(1) - if ch == '': - if not self.handle_eof() and timeout is not None: - # We didn't do anything, but the handle reported EOF. - # We're just going to wait for the timeout period, because otherwise - # we'll just busy wait. - took = time.time() - before - - # For reasons that are unclear, when run under gitlab-runner under MacOS, the - # sleep time here is 5x longer than that we expect, which causes ticks to be - # missed. It is not clear why this happens. However, sleeping smaller fractions - # of the time requested and then waiting until the timeout has expired seems to - # be the only sensible way to deal with this. - while time.time() < before + timeout: - # Sleep in smaller chunks than the requested, so that we don't overrun the - # timeout point by much. - time.sleep(max(timeout - took, 0) / 10) - - ch = None - - else: - ch = sys.stdin.read(1) - - return ch + + else: + ch = sys.stdin.read(1) + + return ch + +except ImportError: + # We're on a Windows-like system; this is entirely tentative as I've never used Pyromaniac on there + import msvcrt + + class Console(ConsoleBase): + # Escape codes found by printing out the codes from the getch calls, below + # Escape codes are preceded by 0x00, or 0xE0. + escape_codes = { + # Standard sequences + 'H': '\x8F', # Up + 'P': '\x8E', # Down + 'M': '\x8D', # Right + 'K': '\x8C', # Left + 'O': '\x8B', # End (Copy in RISC OS terms) + 'I': '\x9F', # Page Up + 'Q': '\x9E', # Page Down + #'R': '\x99', # Insert (don't know what this should be) + #'S': '\x99', # Delete (don't know what this should be) + #'G': '\x8A', # Home (don't know what this should be) + ';': '\x81', # F1 + '<': '\x82', # F2 + '=': '\x83', # F3 + '>': '\x84', # F4 + '?': '\x85', # F5 + '@': '\x86', # F6 + 'A': '\x87', # F7 + 'B': '\x88', # F8 + 'C': '\x89', # F9 + 'D': '\x8A', # F10 + 'E': '\x8B', # F11 + 'F': '\x8C', # F12 + + #'': '\x80', # Print (don't know what this should be, and can't trigger it) + } + + def __init__(self, ro): + #print("Windows terminal started") + super(Console, self).__init__(ro) + self.thread = None + self.alive = True + self.want_key = threading.Event() + self.input_queue = Queue.Queue() + + def finalise(self): + if self.thread: + if self.want_key.is_set(): + # We're currently waiting for a key, so we need to push a character + # into the msvcrt buffer, so that that request exits. + # This message will ONLY appear if you exit the application and the + # msvcrt was waiting for a key press on the console. + print("Pyromaniac exited; please press a key") + # This just causes us to stall until the keypress we were waiting on + # has been entered - probably because there's a mutex inside msvcrt. + # If we DON'T do this, the console will be left in a bad state where + # the keys that are input are the entire input (eg you press a key + # and then cmd says "unknown command "). + msvcrt.putch(' ') + + # Setting the 'want_key' will cause the input pump to wake up + self.want_key.set() + self.alive = False + + # Wait for runner to exit + start = time.time() + while self.thread and time.time() - start < 1.0: + # Wait until that thread exits (or we give up) + time.sleep(0.01) + if self.thread: + print("Console: WARNING: Input pump thread failed to terminate") + + def start_thread(self): + self.thread = threading.Thread(name='Console', target=self.runner) + self.thread.daemon = True + self.thread.start() + + def runner(self): + # Data pump for console input + #print("Input data pump running") + polling_period = 0.5 + while self.alive: + key_requested = self.want_key.wait(polling_period) + if self.alive and key_requested: + # Block here reading the key from the console + key = msvcrt.getch() + self.want_key.clear() + self.input_queue.put(key) + + # We're exiting, so set the thread to None + self.thread = None + + def int_getch(self, timeout=None): + self.want_key.set() + try: + key = self.input_queue.get(True, timeout) + except Queue.Empty: + # No data, so return None + return None + + if key in ('\x00', '\xe0'): + # These magic values precede the escaped codes for the function and cursor keys. + # So now we need another character to check which key it is. + self.want_key.set() + try: + second_key = self.input_queue.get(self.ro.config.input_escapes_timeout) + except Queue.Empty: + # No data, so return the first key + return key + + riscos_key = self.escape_codes.get(second_key, None) + return riscos_key + + return key + + def is_pending(self, timeout=None): + # FIXME: Not sure how to check if there's any input pending, so just say that there is. + return True + + def getch(self, timeout=None): + # Ensure that if they gave us a prompt or line buffered content, it's actually been output + if self.config.flush_output_on_read: + self.flush() + + if not self.thread: + self.start_thread() + + key = self.int_getch(timeout) + return key From b62b89d0b896be6031f40386383a57c3b64ecd56 Mon Sep 17 00:00:00 2001 From: Charles Ferguson Date: Mon, 4 Dec 2023 19:47:47 +0000 Subject: [PATCH 21/65] Add support for disassembling the 6502 code as it executes. There is now a simple disassembler (more than the original one) in the PyBeebicorn code, which can disassemble the code as it is executed. This can be used in a hook to trace only certain sections of the code. --- PyBeebU.py | 21 ++++++- pybeeb/CPU/Dispatch.py | 1 + pybeeb/PyBeebicorn.py | 127 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 146 insertions(+), 3 deletions(-) diff --git a/PyBeebU.py b/PyBeebU.py index eb726f8..eebe2c3 100755 --- a/PyBeebU.py +++ b/PyBeebU.py @@ -50,6 +50,8 @@ def OS_RDCH(pb, address, size, user_data): ch = console.getch() if ch is not None: break + if ch == b'': + raise Exception("EOF") ch = ord(ch) ps = pb.reg_read(PbConstants.PB_6502_REG_PS) if ch == 27: @@ -66,8 +68,10 @@ def OS_RDCH(pb, address, size, user_data): def trace(pb, address, size, user_data): data = pb.mem_read(address, size) - execcode = ' '.join('%02x' % (b,) for b in data) - print("&%04x: %s" % (address, execcode)) + execcode = ' '.join('%02X' % (b,) for b in data) + + (inst, formatted, params, comment) = pb.dis.disassemble(address) + print("&%04X: %-10s : %s %s" % (address, execcode, inst, formatted)) def mem_hook(pb, access, address, size, value, user_data): print("Access %s of &%04x, size %-3i from &%04x" % ('READ' if access == PbConstants.PB_MEM_READ else 'WRITE', @@ -75,8 +79,14 @@ def mem_hook(pb, access, address, size, value, user_data): pb.reg_read(PbConstants.PB_6502_REG_PC))) bbc = BBC() - #bbc.pb.hook_add(PbConstants.PB_HOOK_CODE, trace, begin=0xDEC5, end=0xDF10) + + # Trace all the ROM execution + #bbc.pb.hook_add(PbConstants.PB_HOOK_CODE, trace, begin=0x8000, end=0xC000) + + # Report memory reads and writes around PAGE #bbc.pb.hook_add(PbConstants.PB_HOOK_MEM_READ | PbConstants.PB_HOOK_MEM_WRITE, mem_hook, begin=0xe00, end=0xe01) + + # Report memory reads and writes anywhere between the PAGE and HIMEM (video memory). #bbc.pb.hook_add(PbConstants.PB_HOOK_MEM_READ | PbConstants.PB_HOOK_MEM_WRITE, mem_hook, begin=0xe00, end=0x7c00) syscalls = { OS_WRCH_LOC : OS_WRCH, @@ -84,5 +94,10 @@ def mem_hook(pb, access, address, size, value, user_data): try: console.terminal_init() bbc.go(syscalls) + except Exception as exc: + if str(exc) == 'EOF': + print("\nEOF") + else: + raise finally: console.terminal_reset() diff --git a/pybeeb/CPU/Dispatch.py b/pybeeb/CPU/Dispatch.py index c5f925f..5ebdce6 100644 --- a/pybeeb/CPU/Dispatch.py +++ b/pybeeb/CPU/Dispatch.py @@ -10,6 +10,7 @@ def __init__(self, decoder, addressDispatcher, executionDispatcher, writebackDis self.decoder = decoder self.memory = memory self.registers = registers + self.addressDispatcher = addressDispatcher self.addressTable = { "imp": addressDispatcher.implicit, "acc": addressDispatcher.accumulator, "imm": addressDispatcher.immediate, diff --git a/pybeeb/PyBeebicorn.py b/pybeeb/PyBeebicorn.py index ad2db82..cca0157 100644 --- a/pybeeb/PyBeebicorn.py +++ b/pybeeb/PyBeebicorn.py @@ -63,6 +63,129 @@ def pb_version(): return (major, minor, combined) +class Dissassemble6502(object): + + def __init__(self, decoder): + self.decoder = decoder + self.disassembly_table = { + "imp": self.operands_imp, + "acc": self.operands_acc, + "imm": self.operands_imm, + "zp" : self.operands_zp, + "zpx": self.operands_zpx, + "zpy": self.operands_zpy, + "rel": self.operands_rel, + "abs": self.operands_abs, + "abx": self.operands_abx, + "aby": self.operands_aby, + "ind": self.operands_ind, + "inx": self.operands_inx, + "iny": self.operands_iny, + } + + def operands_imp(self, pc): + return ("", '') + + def operands_acc(self, pc): + return ("", '') + + def operands_imm(self, pc): + b = self.read_byte(pc + 1) + return ("#%s" % (b,), "= &%02X" % (b,) if b > 10 else '') + + def operands_zp(self, pc): + b = self.read_byte(pc + 1) + return ("&%02X" % (b,), '') + + def operands_zpx(self, pc): + b = self.read_byte(pc + 1) + return ("&%02X, X" % (b,), "-> &%02X" % (b + self.reg_x(),)) + + def operands_zpy(self, pc): + b = self.read_byte(pc + 1) + return ("&%02X, Y" % (b,), "-> &%02X" % (b + self.reg_y(),)) + + def operands_rel(self, pc): + return ("&%04X" % (pc + self.read_signedbyte(pc + 1) + 2,), '') + + def operands_abs(self, pc): + return ("&%04X" % (self.read_word(pc + 1),), '') + + def operands_abx(self, pc): + addr = self.read_word(pc + 1) + return ("&%04X, X" % (addr,), "-> &%02X" % (addr + self.reg_x(),)) + + def operands_aby(self, pc): + addr = self.read_word(pc + 1) + return ("&%04X, Y" % (addr,), "-> &%02X" % (addr + self.reg_y(),)) + + def operands_ind(self, pc): + addr = self.read_word(pc + 1) + return ("(&%04X)" % (addr,), "-> &%04X" % (self.read_word(addr)),) + + def operands_inx(self, pc): + addr = self.read_byte(pc + 1) + result = addr + self.reg_x() + result = result & 0xFF + result = self.read_word(addr) + return ("(&%02X, X)" % (addr,), "-> &%04X" % (result,)) + + def operands_iny(self, pc): + addr = self.read_byte(pc + 1) + result = self.read_word(addr) + self.reg_y() + return ("(&%02X), Y" % (addr,), "-> &%04X" % (result,)) + + def read_byte(self, address): + raise NotImplementedError("read_byte not implemented for {}".format(self.__class__.__name__)) + + def read_signedbyte(self, address): + raise NotImplementedError("read_signedbyte not implemented for {}".format(self.__class__.__name__)) + + def read_word(self, address): + raise NotImplementedError("read_word not implemented for {}".format(self.__class__.__name__)) + + def reg_x(self): + raise NotImplementedError("reg_x not implemented for {}".format(self.__class__.__name__)) + + def reg_y(self): + raise NotImplementedError("reg_y not implemented for {}".format(self.__class__.__name__)) + + def disassemble(self, pc): + opcode = self.read_byte(pc) + inst = self.decoder.instruction(opcode) + mode = self.decoder.addressingMode(opcode) + (params, comment) = self.disassembly_table[mode](pc) + if comment: + formatted = "%-8s ; %s" % (params, comment) + else: + formatted = params + return (inst, formatted, params, comment) + + +class Disassemble6502Pb(Dissassemble6502): + def __init__(self, pb): + super(Disassemble6502Pb, self).__init__(pb.dispatch.decoder) + self.pb = pb + + def read_byte(self, address): + return self.pb.memory.readByte(address) + + def read_signedbyte(self, address): + b = self.pb.memory.readByte(address) + if b & 0x80: + b = b - 256 + return b + + def read_word(self, address): + return self.pb.memory.readWord(address) + + def reg_x(self): + return self.pb.reg.x + + def reg_y(self): + return self.pb.reg.y + + class PbHook(object): def __init__(self, pb, htype, callback, user_data=None, begin=1, end=0): @@ -235,6 +358,9 @@ def writeBytes(self, address, value, skip_hook=False): class Pb(object): + """ + PyBeepicorn main object - similar to the Uc() objects in Unicorn. + """ insts_filename = os.path.join(os.path.dirname(__file__), 'insts.csv') def __init__(self): @@ -253,6 +379,7 @@ def __init__(self): self.memory, self.reg) self.bbc = BBCMicro.System.Beeb(self.dispatch) + self.dis = Disassemble6502Pb(self) self.executing = False From 49f46a3cfbb491e32f8e00966887985d023ddccb Mon Sep 17 00:00:00 2001 From: Charles Ferguson Date: Tue, 5 Dec 2023 08:21:49 +0000 Subject: [PATCH 22/65] Add code coverage for the tests that we have. We can now exercise the code in some tests that can be run in a Makefile. Only the coverage run is explicitly supported right now, and it'll fail if the tests fail, so it's a combined coverage and test reporter. We mix the unit tests and the integration tests at the moment, and the output from the integration test isn't checked for regressions. --- DisassembleTest.py | 2 +- Makefile | 20 +++++++ MemoryTests.py | 7 ++- PyBeebU.py | 6 +- coverage_run.py | 124 +++++++++++++++++++++++++++++++++++++++++ pybeeb/Disassembler.py | 2 + requirements.txt | 1 + 7 files changed, 159 insertions(+), 3 deletions(-) create mode 100644 Makefile create mode 100755 coverage_run.py create mode 100644 requirements.txt diff --git a/DisassembleTest.py b/DisassembleTest.py index 650c59f..f4c2ef5 100755 --- a/DisassembleTest.py +++ b/DisassembleTest.py @@ -18,4 +18,4 @@ def main(): if __name__ == '__main__': - main() \ No newline at end of file + main() diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..cbd4e8c --- /dev/null +++ b/Makefile @@ -0,0 +1,20 @@ +# Run our tests + +coverage_clear: + ./coverage_run.py --clear + +coverage_unittest_memory: + ./coverage_run.py --module MemoryTests + +coverage_unittest_disassemble: + ./coverage_run.py --module DisassembleTest + +coverage_inttest_pybeebu: + ./coverage_run.py --module PyBeebU < /dev/null + +coverage: \ + coverage_clear \ + coverage_unittest_memory \ + coverage_unittest_disassemble \ + coverage_inttest_pybeebu + ./coverage_run.py --coverage-report diff --git a/MemoryTests.py b/MemoryTests.py index 1b2e33b..fcd3cab 100755 --- a/MemoryTests.py +++ b/MemoryTests.py @@ -3,6 +3,7 @@ import unittest import pybeeb.CPU.Memory + class MockMapper(object): def __init__(self): self.lastByteRead = None @@ -101,5 +102,9 @@ def test_writeInSecondMap(self): self.assertEqual(self.secondMapper.lastByteWritten, (address - 0x100, (address & 0xff) ^ 0xff)) -if __name__ == '__main__': +def main(): unittest.main() + + +if __name__ == '__main__': + main() diff --git a/PyBeebU.py b/PyBeebU.py index eebe2c3..f1d4ba0 100755 --- a/PyBeebU.py +++ b/PyBeebU.py @@ -30,7 +30,7 @@ def go(self, syscalls): self.pb.hook_del(hook) -if __name__ == "__main__": +def main(): OS_WRCH_LOC = 0xe0a4 OS_RDCH_LOC = 0xdec5 @@ -101,3 +101,7 @@ def mem_hook(pb, access, address, size, value, user_data): raise finally: console.terminal_reset() + + +if __name__ == "__main__": + main() diff --git a/coverage_run.py b/coverage_run.py new file mode 100755 index 0000000..b86d28a --- /dev/null +++ b/coverage_run.py @@ -0,0 +1,124 @@ +#!/usr/bin/env python +""" +Main invocation, but with coverage. + +SUT: Integration tests +Area: All tests within Integration test type +Class: Statistical +Type: Coverage +""" + +import argparse + +import importlib +import json +import os +import sys + +import coverage + +# Files we aren't interested in +omitted_paths = [ + ] +# Packages we will process +package = ['pybeeb'] + + +def update_json_file_with_scm(jsonfile): + """ + Adds extra information to the JSON file for source control information. + + The following values are set: + meta.scm_branch: $CI_BRANCH + meta.scm_hash: $CI_SHA + meta.scm_id: $CI_BRANCH_VERSION + """ + with open(jsonfile, 'r') as fh: + report = json.load(fh) + report['meta']['scm_branch'] = os.environ.get('CI_BRANCH', None) + report['meta']['scm_hash'] = os.environ.get('CI_SHA', None) + report['meta']['scm_id'] = os.environ.get('CI_BRANCH_VERSION', None) + with open(jsonfile, 'w') as fh: + json.dump(report, fh) + + +datafile = os.environ.get('COVERAGE_DATA', 'ci-logs/coverage/data') +htmldir = os.environ.get('COVERAGE_HTML', 'artifacts/coverage/html') +textfile = os.environ.get('COVERAGE_REPORT', 'artifacts/coverage/report.txt') +xmlfile = os.environ.get('COVERAGE_XML', None) +jsonfile = os.environ.get('COVERAGE_JSON', None) + +datadir = os.path.dirname(datafile) +if not os.path.isdir(datadir): + os.makedirs(datadir) +if not os.path.isdir(htmldir): + os.makedirs(htmldir) +reportdir = os.path.dirname(textfile) +if not os.path.isdir(reportdir): + os.makedirs(reportdir) +if xmlfile is None: + if '.txt' in textfile: + xmlfile = textfile.replace(".txt", ".xml") + else: + xmlfile += ".xml" +if jsonfile is None: + if '.txt' in textfile: + jsonfile = textfile.replace(".txt", ".json") + else: + jsonfile += ".json" + + +parser = argparse.ArgumentParser(add_help=False) +parser.add_argument('--module', default='PyBeebU', + help="Module to run with coverage") +parser.add_argument('--coverage-report', action='store_true', default=False, + help="Generate report for collected coverage information") +parser.add_argument('--clear', action='store_true', default=False, + help="Clear all the coverage information before running") + +(options, unknown) = parser.parse_known_args() +sys.argv = [options.module + '.py'] + list(unknown) + +package.append(options.module) + +cov = coverage.Coverage(data_file=datafile, auto_data=True, branch=True, source=package, concurrency='thread') + + +if options.coverage_report: + cov.load() + + print("Generate HTML report") + cov.html_report(directory=htmldir, omit=omitted_paths) + + print("Generate text report") + with open(textfile, 'w') as fh: + coverage = cov.report(file=fh, omit=omitted_paths) + + print("Generate JSON report") + coverage = cov.json_report(outfile=jsonfile, omit=omitted_paths) + update_json_file_with_scm(jsonfile) + + print("Generate XML report") + coverage = cov.xml_report(outfile=xmlfile, omit=omitted_paths) + + print("Overall Coverage: %.3f%%" % (coverage,)) + result = 0 + +else: + if options.clear: + cov.erase() + result = 0 + else: + # Reset the arguments to those that were passed on + unknown.insert(0, sys.argv[0]) + sys.argv = unknown + + # Run pyro with coverage enabled + cov.start() + mod = importlib.import_module(options.module) + sys.modules[options.module] = mod + setattr(sys.modules['__main__'], options.module, mod) + result = mod.main() + cov.stop() + +sys.exit(result) diff --git a/pybeeb/Disassembler.py b/pybeeb/Disassembler.py index 72aa8c4..4b5693b 100644 --- a/pybeeb/Disassembler.py +++ b/pybeeb/Disassembler.py @@ -238,3 +238,5 @@ def disassemble(self, data): for decode in generator: print( "%s " % (self.registers.pc)), print(": %s " % (decode)) + if self.registers.pc >= len(data): + break diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..10a676a --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +coverage == 5.5 From c8df945ef0db686ba91fd18fa0e72dae9ca2e9d5 Mon Sep 17 00:00:00 2001 From: Charles Ferguson Date: Tue, 5 Dec 2023 08:23:51 +0000 Subject: [PATCH 23/65] Add github workflow to run the coverage/tests on pushes. There is a simple workflow here to run the coverage and tests on push. We're only running under Python 2, still, but it should be sufficient to make it work for us. --- .github/workflows/ci.yml | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..6ae9876 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,34 @@ +--- +# Automatic testing +# + +name: Tests + +# Controls when the action will run. Triggers the workflow on: +# * push on any branch. +# * tag creation for tags beginning with a 'v' +on: + push: + branches: ["*"] + tags: ["v*"] + # Pull request events happen on pull request state transitions, so we probably don't want this here. + #pull_request: + # branches: ["*"] + +jobs: + coverage: + runs-on: ubuntu-20.04 + steps: + - uses: actions/checkout@v3 + + - name: Prepare packages + run: | + sudo apt-get install -y python2 virtualenv + virtualenv -p python2 venv + source venv/bin/activate && \ + pip install -r requirements.txt + + - name: Run the coverage tests + run: | + source venv/bin/activate && \ + timeout 60 make coverage From afe9090553e85ca79207d6127a9eb30916fedea6 Mon Sep 17 00:00:00 2001 From: Charles Ferguson Date: Thu, 7 Dec 2023 00:22:32 +0000 Subject: [PATCH 24/65] Rework the OSInterfaces in the example program. The PyBeepicorn example program now has some more abstracted interface entry points. These are set up in such a way that we can use them without (in theory) having the knowledge of the underlying system. They should be easy to extend for the other APIs. --- PyBeebU.py | 112 +++++++++++++++++++++++++++++++++-------- pybeeb/CPU/Dispatch.py | 13 +++++ pybeeb/PyBeebicorn.py | 25 +++++++-- 3 files changed, 124 insertions(+), 26 deletions(-) diff --git a/PyBeebU.py b/PyBeebU.py index f1d4ba0..0270ded 100755 --- a/PyBeebU.py +++ b/PyBeebU.py @@ -30,41 +30,96 @@ def go(self, syscalls): self.pb.hook_del(hook) -def main(): - OS_WRCH_LOC = 0xe0a4 - OS_RDCH_LOC = 0xdec5 +class OSInterface(object): + code = 0x0000 + vector = 0x200 + + def __init__(self): + """ + Initialise the interface. + """ + pass + + def start(self): + """ + System is starting; prepare the interface for use. + """ + pass + + def stop(self): + """ + System is stopping; shut down the interface. + """ + pass + + def call(self, regs, memory): + """ + Call the interface with a given set of parameters. - console = Console() + The Registers and Memory will be updated on return. - def OS_WRCH(pb, address, size, user_data): - c = pb.reg_read(PbConstants.PB_6502_REG_A) - if c == 127: + @param regs: Registers object, containing a, x, y, pc, and sp properties + the flags + @param memory: Memory object, containing the (read|write)(Byte|Bytes|Word|SignedByte) methods + + @return: True if the call has been handled (return from interface), + False if call should continue at the code execution point + """ + return False + + +class OSWRCH(OSInterface): + code = 0xE0A4 + vector = 0x020E + + def call(self, regs, memory): + if regs.a == 127: sys.stdout.write('\x08 \x08') else: - sys.stdout.write(chr(c)) + sys.stdout.write(chr(regs.a)) + + # Return immediately with an RTS + return True - def OS_RDCH(pb, address, size, user_data): + +class OSRDCH(OSInterface): + code = 0xDEC5 + vector = 0x0210 + + def __init__(self): + super(OSRDCH, self).__init__() + self.console = Console() + + def start(self): + self.console.terminal_init() + + def end(self): + self.console.terminal_reset() + + def call(self, regs, memory): # See: https://mdfs.net/Docs/Comp/BBC/OS1-20/DC1C #print "OS_RDCH" # Could inject keypresses here maybe? while True: - ch = console.getch() + ch = self.console.getch() if ch is not None: break if ch == b'': raise Exception("EOF") ch = ord(ch) - ps = pb.reg_read(PbConstants.PB_6502_REG_PS) if ch == 27: - ps |= PbConstants.PB_6502_FLAG_CARRY + regs.carry = True # Bit of a hack as we don't have interrupts # Set the escape flag - pb.mem_write(0xFF, bytearray([0x80])) + memory.writeByte(0xFF, 0x80) else: - ps &= ~PbConstants.PB_6502_FLAG_CARRY - pb.reg_write(PbConstants.PB_6502_REG_PS, ps) - pb.reg_write(PbConstants.PB_6502_REG_A, ch) - pb.reg_write(PbConstants.PB_6502_REG_PC, 0xDF0B) # RTS instruction + regs.carry = False + regs.a = ch + + # Return immediately with an RTS + return True + + +def main(): def trace(pb, address, size, user_data): data = pb.mem_read(address, size) @@ -89,10 +144,24 @@ def mem_hook(pb, access, address, size, value, user_data): # Report memory reads and writes anywhere between the PAGE and HIMEM (video memory). #bbc.pb.hook_add(PbConstants.PB_HOOK_MEM_READ | PbConstants.PB_HOOK_MEM_WRITE, mem_hook, begin=0xe00, end=0x7c00) - syscalls = { OS_WRCH_LOC : OS_WRCH, - OS_RDCH_LOC : OS_RDCH } + interface_classes = ( + OSWRCH, + OSRDCH + ) try: - console.terminal_init() + syscalls = {} + interfaces = [] + for cls in interface_classes: + interface = cls() + interface.start() + interfaces.append(interface) + def hook(pb, address, size, user_data, interface=interface): + handled = interface.call(pb.reg, pb.memory) + if handled: + pb.reg.pc = pb.dispatch.pullWord() + 1 + + syscalls[interface.code] = hook + bbc.go(syscalls) except Exception as exc: if str(exc) == 'EOF': @@ -100,7 +169,8 @@ def mem_hook(pb, access, address, size, value, user_data): else: raise finally: - console.terminal_reset() + for interfaces in reversed(interfaces): + interface.end() if __name__ == "__main__": diff --git a/pybeeb/CPU/Dispatch.py b/pybeeb/CPU/Dispatch.py index 5ebdce6..06b9ac7 100644 --- a/pybeeb/CPU/Dispatch.py +++ b/pybeeb/CPU/Dispatch.py @@ -11,6 +11,7 @@ def __init__(self, decoder, addressDispatcher, executionDispatcher, writebackDis self.memory = memory self.registers = registers self.addressDispatcher = addressDispatcher + self.executionDispatcher = executionDispatcher self.addressTable = { "imp": addressDispatcher.implicit, "acc": addressDispatcher.accumulator, "imm": addressDispatcher.immediate, @@ -164,3 +165,15 @@ def reset(self): self.registers.reset() reset_handler = self.memory.readWord(0xfffc) self.registers.pc = reset_handler + + def pushByte(self, value): + self.executionDispatcher.pushByte(value) + + def pushWord(self, value): + self.executionDispatcher.pushWord(value) + + def pullByte(self): + return self.executionDispatcher.pullByte() + + def pullWord(self): + return self.executionDispatcher.pullWord() diff --git a/pybeeb/PyBeebicorn.py b/pybeeb/PyBeebicorn.py index cca0157..b886fb4 100644 --- a/pybeeb/PyBeebicorn.py +++ b/pybeeb/PyBeebicorn.py @@ -399,12 +399,27 @@ def write_x(v): def write_y(v): self.reg.y = v & 0xFF + def read_pc(): + return self.reg.pc & 0xFFFF + + def read_sp(): + return self.reg.sp & 0xFF + + def read_a(): + return self.reg.a & 0xFF + + def read_x(): + return self.reg.x & 0xFF + + def read_y(): + return self.reg.y & 0xFF + self.reg_dispatch = { - PbConstants.PB_6502_REG_PC: (lambda: self.reg.pc, write_pc), - PbConstants.PB_6502_REG_SP: (lambda: self.reg.sp, write_sp), - PbConstants.PB_6502_REG_A: (lambda: self.reg.a, write_a), - PbConstants.PB_6502_REG_X: (lambda: self.reg.x, write_x), - PbConstants.PB_6502_REG_Y: (lambda: self.reg.y, write_y), + PbConstants.PB_6502_REG_PC: (read_pc, write_pc), + PbConstants.PB_6502_REG_SP: (read_sp, write_sp), + PbConstants.PB_6502_REG_A: (read_a, write_a), + PbConstants.PB_6502_REG_X: (read_x, write_x), + PbConstants.PB_6502_REG_Y: (read_y, write_y), PbConstants.PB_6502_REG_PS: (lambda: self.reg.ps(), lambda v: self.reg.setPS(v)), } From 5e8ec793767df7254cee8affe326dab0e6f6adc3 Mon Sep 17 00:00:00 2001 From: Charles Ferguson Date: Thu, 7 Dec 2023 08:53:02 +0000 Subject: [PATCH 25/65] Add an OSCLI handler to allow exiting. We now have a very simple OSCLI handler so that we can trap *QUIT and exit the emulator. If we don't recognise the command it is passed to the rest of the handler system. --- PyBeebU.py | 30 +++++++++++++++++++++++++++--- pybeeb/CPU/Memory.py | 11 +++++++++++ 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/PyBeebU.py b/PyBeebU.py index 0270ded..560db20 100755 --- a/PyBeebU.py +++ b/PyBeebU.py @@ -92,7 +92,7 @@ def __init__(self): def start(self): self.console.terminal_init() - def end(self): + def stop(self): self.console.terminal_reset() def call(self, regs, memory): @@ -119,6 +119,29 @@ def call(self, regs, memory): return True +class OSCLI(OSInterface): + code = 0xDF89 + vector = 0x0208 + + def call(self, regs, memory): + xy = regs.x | (regs.y << 8) + cli = memory.readString(xy) + while cli[0] == '*': + cli = cli[1:] + if ' ' in cli: + (command, args) = cli.split(' ', 1) + else: + command = cli + args = '' + + return self.command(command.upper(), args) + + def command(self, command, args): + if command == 'QUIT': + sys.exit() + return False + + def main(): def trace(pb, address, size, user_data): @@ -146,7 +169,8 @@ def mem_hook(pb, access, address, size, value, user_data): interface_classes = ( OSWRCH, - OSRDCH + OSRDCH, + OSCLI ) try: syscalls = {} @@ -170,7 +194,7 @@ def hook(pb, address, size, user_data, interface=interface): raise finally: for interfaces in reversed(interfaces): - interface.end() + interface.stop() if __name__ == "__main__": diff --git a/pybeeb/CPU/Memory.py b/pybeeb/CPU/Memory.py index 05b0d14..9b49542 100644 --- a/pybeeb/CPU/Memory.py +++ b/pybeeb/CPU/Memory.py @@ -199,3 +199,14 @@ def readSignedByte(self, address): def readWord(self, address): return self.readByte(address) + (self.readByte(address + 1) << 8) + + def readString(self, address): + s = [] + while True: + b = self.readByte(address) + if b == 13 or b == 0: + break + s.append(b) + address += 1 + + return bytes(bytearray(s)) From d3683697a94318cdb5fa9719af7ee06f763150cb Mon Sep 17 00:00:00 2001 From: Charles Ferguson Date: Fri, 8 Dec 2023 08:28:56 +0000 Subject: [PATCH 26/65] Add OSBYTE and OSWORD hooked classes. We now have classes which are hookable so that we can replace the OSBYTE and OSWORD implementations. This allows us to provide some interfaces to the host system which override the BBC implementation. --- PyBeebU.py | 162 +++++++++++++++++++++++++++++++++++++++++++++++++---- console.py | 79 +++++++++++++++----------- 2 files changed, 197 insertions(+), 44 deletions(-) diff --git a/PyBeebU.py b/PyBeebU.py index 560db20..c6ecff9 100755 --- a/PyBeebU.py +++ b/PyBeebU.py @@ -23,13 +23,25 @@ def go(self, syscalls): hooks.append(self.pb.hook_add(PbConstants.PB_HOOK_CODE, func, begin=addr, end=addr + 1)) - self.pb.emu_start(self.pb.reg_read(PbConstants.PB_6502_REG_PC), -1) + self.pb.emu_start(self.pb.reg_read(PbConstants.PB_6502_REG_PC), -2) finally: # Deregister the entry points for hook in hooks: self.pb.hook_del(hook) +class BBCError(Exception): + + def __init__(self, errnum, errmess): + self.errnum = errnum + self.errmess = errmess + super(BBCError, self).__init__(errmess, errnum) + + +class InputEOFError(Exception): + pass + + class OSInterface(object): code = 0x0000 vector = 0x200 @@ -58,6 +70,8 @@ def call(self, regs, memory): The Registers and Memory will be updated on return. + May raise exception BBCError to indicate that an error should be reported. + @param regs: Registers object, containing a, x, y, pc, and sp properties + the flags @param memory: Memory object, containing the (read|write)(Byte|Bytes|Word|SignedByte) methods @@ -103,7 +117,7 @@ def call(self, regs, memory): if ch is not None: break if ch == b'': - raise Exception("EOF") + raise InputEOFError("EOF received from terminal") ch = ord(ch) if ch == 27: regs.carry = True @@ -142,6 +156,126 @@ def command(self, command, args): return False +class OSBYTE(OSInterface): + code = 0xE772 + vector = 0x020A + + def __init__(self): + super(OSBYTE, self).__init__() + + # The dispatch dictionary contains the functions that should be + # dispatched to handle OSBYTE calls. + # The keys in the dictionary may be one of: + # (A, X, Y) + # (A, X) + # A + # The value of the first matched key will be used as the + # dispatcher. + # If no matching key exists, the method `osbyte` will be used. + # The dispatcher used will be called with the parameters + # `(A, X, Y, regs, memory)`. + self.dispatch = { + (0x00, 0x00): self.osbyte_osversion_error, + } + + def call(self, regs, memory): + dispatcher = self.dispatch.get((regs.a, regs.x, regs.y), None) + if dispatcher is None: + dispatcher = self.dispatch.get((regs.a, regs.x), None) + if dispatcher is None: + dispatcher = self.dispatch.get(regs.a, None) + if dispatcher is None: + dispatcher = self.osbyte + return dispatcher(regs.a, regs.x, regs.y, regs, memory) + + def osbyte_osversion_error(self, a, x, y, regs, memory): + raise BBCError(247, "OS 1.20 (PyBeeb)") + + def osbyte(self, a, x, y, regs, memory): + return False + + +class OSWORD(OSInterface): + code = 0xE7EB + vector = 0x020C + + def __init__(self): + super(OSWORD, self).__init__() + self.console = Console() + + # The dispatch dictionary contains the functions that should be + # dispatched to handle OSBYTE calls. + # The keys in the dictionary may the value of the A register. + # If no matching key exists, the method `osword` will be used. + # The dispatcher used will be called with the parameters + # `(a, address, regs, memory)`. + self.dispatch = { + 0x00: self.osword_readline, + } + + def call(self, regs, memory): + dispatcher = self.dispatch.get(regs.a, None) + if dispatcher is None: + dispatcher = self.osword + + address = regs.x | (regs.y << 8) + return dispatcher(regs.a, address, regs, memory) + + def osword_readline(self, a, address, regs, memory): + # The parameter block: + # XY+ 0 Buffer address for input LSB + # 1 MSB + # 2 Maximum line length + # 3 Minimum acceptable ASCII value + # 4 Maximum acceptable ASCII value + # + # Only characters greater or equal to XY+3 and lesser or equal to + # XY+4 will be accepted. + # + # On exit, C=0 if a carriage return terminated input. + # C=1 if an ESCAPE condition terminated input. + # Y contains line length, including carriage return if + # used. + input_memory = memory.readWord(address) + maxline = memory.readByte(address + 2) + lowest = memory.readByte(address + 3) + highest = memory.readByte(address + 4) + + console_active = self.console.terminal_active + if console_active: + self.console.terminal_reset() + try: + sys.stdout.flush() + result = self.read_line() + result = result[:maxline - 1] + result = result + '\r' + # FIXME: Note that the lowest and highest are not honoured by this + regs.carry = False + regs.Y = len(result) + memory.writeBytes(input_memory, bytearray(result)) + + except EOFError: + raise InputEOFError("EOF received from terminal") + + except KeyboardInterrupt: + regs.carry = True + regs.Y = 0 + + if console_active: + self.console.terminal_init() + + return True + + def read_line(self): + """ + Read a line of input; override with any other ReadLine implementation. + """ + return raw_input() + + def osword(self, a, address, regs, memory): + return False + + def main(): def trace(pb, address, size, user_data): @@ -170,7 +304,9 @@ def mem_hook(pb, access, address, size, value, user_data): interface_classes = ( OSWRCH, OSRDCH, - OSCLI + OSCLI, + OSBYTE, + OSWORD, ) try: syscalls = {} @@ -180,18 +316,22 @@ def mem_hook(pb, access, address, size, value, user_data): interface.start() interfaces.append(interface) def hook(pb, address, size, user_data, interface=interface): - handled = interface.call(pb.reg, pb.memory) - if handled: - pb.reg.pc = pb.dispatch.pullWord() + 1 + try: + handled = interface.call(pb.reg, pb.memory) + if handled: + pb.reg.pc = pb.dispatch.pullWord() + 1 + except BBCError as exc: + pb.memory.writeBytes(0x100, bytearray([0, exc.errnum])) + pb.memory.writeBytes(0x100 + 2, bytearray(exc.errmess)) + pb.reg.pc = 0x100 syscalls[interface.code] = hook bbc.go(syscalls) - except Exception as exc: - if str(exc) == 'EOF': - print("\nEOF") - else: - raise + + except InputEOFError as exc: + print("\nEOF") + finally: for interfaces in reversed(interfaces): interface.stop() diff --git a/console.py b/console.py index be90984..cdb207b 100644 --- a/console.py +++ b/console.py @@ -18,21 +18,31 @@ class ConsoleBase(object): """ Console management from the host enviroment. """ + _singleton = None + _inited = False + + def __new__(cls, *args, **kwargs): + print("Singleton creation %r" % (cls._singleton)) + if not cls._singleton: + cls._singleton = super(ConsoleBase, cls).__new__(cls, *args, **kwargs) + return cls._singleton # FIXME: It's arguable that the console input should run continually in a thread # and push keys into buffers. def __init__(self): - super(ConsoleBase, self).__init__() - self.inited = False - self.cooked_newlines = True - self.output = sys.stdout + if not self._inited: + super(ConsoleBase, self).__init__() + self.terminal_active = False + self.cooked_newlines = True + self.output = sys.stdout + self._inited = True def terminal_init(self): - self.inited = True + self.terminal_active = True def terminal_reset(self): - self.inited = False + self.terminal_active = False def encode(self, uni): """ @@ -60,7 +70,7 @@ def finalise(self): # We don't want the base class messing with our configuration. return - if self.inited: + if self.terminal_active: self.terminal_reset() def getch(self, timeout=None): @@ -168,23 +178,24 @@ class Console(ConsoleBase): } def __init__(self): - super(Console, self).__init__() - self.fd = None - self.is_tty = False - self.is_dead = False - self.old_settings = None - self.intbuf = array.array('i', [0]) - self.config = ConsoleConfig() - self.original_stdout = sys.__stdout__ - - # ANSI Escape handling - self.in_utf8_sequence = [] - self.in_escape_sequence = [] - self.in_utf8 = False - self.in_escape = None - - self.debug_inputescapes = False - self.debug_inpututf8 = False + if not self._inited: + super(Console, self).__init__() + self.fd = None + self.is_tty = False + self.is_dead = False + self.old_settings = None + self.intbuf = array.array('i', [0]) + self.config = ConsoleConfig() + self.original_stdout = sys.__stdout__ + + # ANSI Escape handling + self.in_utf8_sequence = [] + self.in_escape_sequence = [] + self.in_utf8 = False + self.in_escape = None + + self.debug_inputescapes = False + self.debug_inpututf8 = False def get_fd(self): try: @@ -523,13 +534,15 @@ class Console(ConsoleBase): #'': '\x80', # Print (don't know what this should be, and can't trigger it) } - def __init__(self, ro): - #print("Windows terminal started") - super(Console, self).__init__(ro) - self.thread = None - self.alive = True - self.want_key = threading.Event() - self.input_queue = Queue.Queue() + def __init__(self): + if not self._inited: + #print("Windows terminal started") + super(Console, self).__init__() + self.config = ConsoleConfig() + self.thread = None + self.alive = True + self.want_key = threading.Event() + self.input_queue = Queue.Queue() def finalise(self): if self.thread: @@ -538,7 +551,7 @@ def finalise(self): # into the msvcrt buffer, so that that request exits. # This message will ONLY appear if you exit the application and the # msvcrt was waiting for a key press on the console. - print("Pyromaniac exited; please press a key") + print("System exited; please press a key") # This just causes us to stall until the keypress we were waiting on # has been entered - probably because there's a mutex inside msvcrt. # If we DON'T do this, the console will be left in a bad state where @@ -591,7 +604,7 @@ def int_getch(self, timeout=None): # So now we need another character to check which key it is. self.want_key.set() try: - second_key = self.input_queue.get(self.ro.config.input_escapes_timeout) + second_key = self.input_queue.get(self.config.input_escapes_timeout) except Queue.Empty: # No data, so return the first key return key From 17d5702ed57e0c55cfa74401032e757a93935d2b Mon Sep 17 00:00:00 2001 From: Charles Ferguson Date: Fri, 8 Dec 2023 08:54:28 +0000 Subject: [PATCH 27/65] Move all the host interfaces for the BBC MOS to a package. The host interfaces have now moved into a package so that they can be used more generically if people want. Specific routines that interface with the host are separate from the base implementations so that they don't have to be the way that you communicate with the system. --- PyBeebU.py | 250 ++------------------------- pybeeb/Host/__init__.py | 5 + pybeeb/Host/base.py | 239 +++++++++++++++++++++++++ console.py => pybeeb/Host/console.py | 2 +- pybeeb/Host/host.py | 78 +++++++++ 5 files changed, 335 insertions(+), 239 deletions(-) create mode 100644 pybeeb/Host/__init__.py create mode 100644 pybeeb/Host/base.py rename console.py => pybeeb/Host/console.py (99%) create mode 100644 pybeeb/Host/host.py diff --git a/PyBeebU.py b/PyBeebU.py index c6ecff9..0a1419b 100755 --- a/PyBeebU.py +++ b/PyBeebU.py @@ -8,11 +8,12 @@ import sys from pybeeb.PyBeebicorn import Pb, PbError, PbConstants -from console import Console +from pybeeb.Host import BBCError, InputEOFError, OSCLI, OSBYTE, OSInterface +from pybeeb.Host.host import OSWRCHtty, OSRDCHtty, OSWORDtty class BBC(object): - def __init__(self, pcTrace = False, verbose = False): + def __init__(self, pcTrace=False, verbose=False): self.pb = Pb() def go(self, syscalls): @@ -30,125 +31,7 @@ def go(self, syscalls): self.pb.hook_del(hook) -class BBCError(Exception): - - def __init__(self, errnum, errmess): - self.errnum = errnum - self.errmess = errmess - super(BBCError, self).__init__(errmess, errnum) - - -class InputEOFError(Exception): - pass - - -class OSInterface(object): - code = 0x0000 - vector = 0x200 - - def __init__(self): - """ - Initialise the interface. - """ - pass - - def start(self): - """ - System is starting; prepare the interface for use. - """ - pass - - def stop(self): - """ - System is stopping; shut down the interface. - """ - pass - - def call(self, regs, memory): - """ - Call the interface with a given set of parameters. - - The Registers and Memory will be updated on return. - - May raise exception BBCError to indicate that an error should be reported. - - @param regs: Registers object, containing a, x, y, pc, and sp properties + the flags - @param memory: Memory object, containing the (read|write)(Byte|Bytes|Word|SignedByte) methods - - @return: True if the call has been handled (return from interface), - False if call should continue at the code execution point - """ - return False - - -class OSWRCH(OSInterface): - code = 0xE0A4 - vector = 0x020E - - def call(self, regs, memory): - if regs.a == 127: - sys.stdout.write('\x08 \x08') - else: - sys.stdout.write(chr(regs.a)) - - # Return immediately with an RTS - return True - - -class OSRDCH(OSInterface): - code = 0xDEC5 - vector = 0x0210 - - def __init__(self): - super(OSRDCH, self).__init__() - self.console = Console() - - def start(self): - self.console.terminal_init() - - def stop(self): - self.console.terminal_reset() - - def call(self, regs, memory): - # See: https://mdfs.net/Docs/Comp/BBC/OS1-20/DC1C - #print "OS_RDCH" # Could inject keypresses here maybe? - while True: - ch = self.console.getch() - if ch is not None: - break - if ch == b'': - raise InputEOFError("EOF received from terminal") - ch = ord(ch) - if ch == 27: - regs.carry = True - - # Bit of a hack as we don't have interrupts - # Set the escape flag - memory.writeByte(0xFF, 0x80) - else: - regs.carry = False - regs.a = ch - - # Return immediately with an RTS - return True - - -class OSCLI(OSInterface): - code = 0xDF89 - vector = 0x0208 - - def call(self, regs, memory): - xy = regs.x | (regs.y << 8) - cli = memory.readString(xy) - while cli[0] == '*': - cli = cli[1:] - if ' ' in cli: - (command, args) = cli.split(' ', 1) - else: - command = cli - args = '' - - return self.command(command.upper(), args) +class OSCLIquit(OSCLI): def command(self, command, args): if command == 'QUIT': @@ -156,125 +39,16 @@ def command(self, command, args): return False -class OSBYTE(OSInterface): - code = 0xE772 - vector = 0x020A +class OSBYTEversion(OSBYTE): def __init__(self): - super(OSBYTE, self).__init__() - - # The dispatch dictionary contains the functions that should be - # dispatched to handle OSBYTE calls. - # The keys in the dictionary may be one of: - # (A, X, Y) - # (A, X) - # A - # The value of the first matched key will be used as the - # dispatcher. - # If no matching key exists, the method `osbyte` will be used. - # The dispatcher used will be called with the parameters - # `(A, X, Y, regs, memory)`. - self.dispatch = { - (0x00, 0x00): self.osbyte_osversion_error, - } + super(OSBYTEversion, self).__init__() - def call(self, regs, memory): - dispatcher = self.dispatch.get((regs.a, regs.x, regs.y), None) - if dispatcher is None: - dispatcher = self.dispatch.get((regs.a, regs.x), None) - if dispatcher is None: - dispatcher = self.dispatch.get(regs.a, None) - if dispatcher is None: - dispatcher = self.osbyte - return dispatcher(regs.a, regs.x, regs.y, regs, memory) + self.dispatch[(0x00, 0x00)] = self.osbyte_osversion_error def osbyte_osversion_error(self, a, x, y, regs, memory): raise BBCError(247, "OS 1.20 (PyBeeb)") - def osbyte(self, a, x, y, regs, memory): - return False - - -class OSWORD(OSInterface): - code = 0xE7EB - vector = 0x020C - - def __init__(self): - super(OSWORD, self).__init__() - self.console = Console() - - # The dispatch dictionary contains the functions that should be - # dispatched to handle OSBYTE calls. - # The keys in the dictionary may the value of the A register. - # If no matching key exists, the method `osword` will be used. - # The dispatcher used will be called with the parameters - # `(a, address, regs, memory)`. - self.dispatch = { - 0x00: self.osword_readline, - } - - def call(self, regs, memory): - dispatcher = self.dispatch.get(regs.a, None) - if dispatcher is None: - dispatcher = self.osword - - address = regs.x | (regs.y << 8) - return dispatcher(regs.a, address, regs, memory) - - def osword_readline(self, a, address, regs, memory): - # The parameter block: - # XY+ 0 Buffer address for input LSB - # 1 MSB - # 2 Maximum line length - # 3 Minimum acceptable ASCII value - # 4 Maximum acceptable ASCII value - # - # Only characters greater or equal to XY+3 and lesser or equal to - # XY+4 will be accepted. - # - # On exit, C=0 if a carriage return terminated input. - # C=1 if an ESCAPE condition terminated input. - # Y contains line length, including carriage return if - # used. - input_memory = memory.readWord(address) - maxline = memory.readByte(address + 2) - lowest = memory.readByte(address + 3) - highest = memory.readByte(address + 4) - - console_active = self.console.terminal_active - if console_active: - self.console.terminal_reset() - try: - sys.stdout.flush() - result = self.read_line() - result = result[:maxline - 1] - result = result + '\r' - # FIXME: Note that the lowest and highest are not honoured by this - regs.carry = False - regs.Y = len(result) - memory.writeBytes(input_memory, bytearray(result)) - - except EOFError: - raise InputEOFError("EOF received from terminal") - - except KeyboardInterrupt: - regs.carry = True - regs.Y = 0 - - if console_active: - self.console.terminal_init() - - return True - - def read_line(self): - """ - Read a line of input; override with any other ReadLine implementation. - """ - return raw_input() - - def osword(self, a, address, regs, memory): - return False - def main(): @@ -302,11 +76,11 @@ def mem_hook(pb, access, address, size, value, user_data): #bbc.pb.hook_add(PbConstants.PB_HOOK_MEM_READ | PbConstants.PB_HOOK_MEM_WRITE, mem_hook, begin=0xe00, end=0x7c00) interface_classes = ( - OSWRCH, - OSRDCH, - OSCLI, - OSBYTE, - OSWORD, + OSWRCHtty, + OSRDCHtty, + OSCLIquit, + OSBYTEversion, + OSWORDtty, ) try: syscalls = {} diff --git a/pybeeb/Host/__init__.py b/pybeeb/Host/__init__.py new file mode 100644 index 0000000..40cd91a --- /dev/null +++ b/pybeeb/Host/__init__.py @@ -0,0 +1,5 @@ +""" +Implementations of Interfaces to the BBC MOS which we can trap. +""" + +from base import * diff --git a/pybeeb/Host/base.py b/pybeeb/Host/base.py new file mode 100644 index 0000000..33d9077 --- /dev/null +++ b/pybeeb/Host/base.py @@ -0,0 +1,239 @@ +""" +Base classes for the implementations of host interfaces. +""" + +import sys + + +__all__ = ( + 'BBCError', + 'InputEOFError', + 'OSInterface', + 'OSBYTE', + 'OSWORD', + 'OSCLI', + 'OSWRCH', + 'OSRDCH' + ) + + +class BBCError(Exception): + + def __init__(self, errnum, errmess): + self.errnum = errnum + self.errmess = errmess + super(BBCError, self).__init__(errmess, errnum) + + +class InputEOFError(Exception): + pass + + +class OSInterface(object): + code = 0x0000 + vector = 0x200 + + def __init__(self): + """ + Initialise the interface. + """ + pass + + def start(self): + """ + System is starting; prepare the interface for use. + """ + pass + + def stop(self): + """ + System is stopping; shut down the interface. + """ + pass + + def call(self, regs, memory): + """ + Call the interface with a given set of parameters. + + The Registers and Memory will be updated on return. + + May raise exception BBCError to indicate that an error should be reported. + + @param regs: Registers object, containing a, x, y, pc, and sp properties + the flags + @param memory: Memory object, containing the (read|write)(Byte|Bytes|Word|SignedByte) methods + + @return: True if the call has been handled (return from interface), + False if call should continue at the code execution point + """ + return False + + +class OSWRCH(OSInterface): + code = 0xE0A4 + vector = 0x020E + + def call(self, regs, memory): + return self.writec(regs.a) + + def writec(self, ch): + """ + Write a BBC VDU code to the output stream. + """ + return False + + +class OSRDCH(OSInterface): + code = 0xDEC5 + vector = 0x0210 + + def call(self, regs, memory): + ch = self.readc() + if ch is None: + return False + + ch = ord(ch) + if ch == 27: + regs.carry = True + + # Bit of a hack as we don't have interrupts + # Set the escape flag + memory.writeByte(0xFF, 0x80) + else: + regs.carry = False + regs.a = ch + + # Return immediately with an RTS + return True + + def readc(self): + return None + + +class OSCLI(OSInterface): + code = 0xDF89 + vector = 0x0208 + + def call(self, regs, memory): + xy = regs.x | (regs.y << 8) + cli = memory.readString(xy) + while cli[0] == '*': + cli = cli[1:] + if ' ' in cli: + (command, args) = cli.split(' ', 1) + else: + command = cli + args = '' + + return self.command(command.upper(), args) + + def command(self, command, args): + return False + + +class OSBYTE(OSInterface): + code = 0xE772 + vector = 0x020A + + def __init__(self): + super(OSBYTE, self).__init__() + + # The dispatch dictionary contains the functions that should be + # dispatched to handle OSBYTE calls. + # The keys in the dictionary may be one of: + # (A, X, Y) + # (A, X) + # A + # The value of the first matched key will be used as the + # dispatcher. + # If no matching key exists, the method `osbyte` will be used. + # The dispatcher used will be called with the parameters + # `(A, X, Y, regs, memory)`. + self.dispatch = { + } + + def call(self, regs, memory): + dispatcher = self.dispatch.get((regs.a, regs.x, regs.y), None) + if dispatcher is None: + dispatcher = self.dispatch.get((regs.a, regs.x), None) + if dispatcher is None: + dispatcher = self.dispatch.get(regs.a, None) + if dispatcher is None: + dispatcher = self.osbyte + return dispatcher(regs.a, regs.x, regs.y, regs, memory) + + def osbyte(self, a, x, y, regs, memory): + return False + + +class OSWORD(OSInterface): + code = 0xE7EB + vector = 0x020C + + def __init__(self): + super(OSWORD, self).__init__() + + # The dispatch dictionary contains the functions that should be + # dispatched to handle OSBYTE calls. + # The keys in the dictionary may the value of the A register. + # If no matching key exists, the method `osword` will be used. + # The dispatcher used will be called with the parameters + # `(a, address, regs, memory)`. + self.dispatch = { + 0x00: self.osword_readline, + } + + def call(self, regs, memory): + dispatcher = self.dispatch.get(regs.a, None) + if dispatcher is None: + dispatcher = self.osword + + address = regs.x | (regs.y << 8) + return dispatcher(regs.a, address, regs, memory) + + def osword_readline(self, a, address, regs, memory): + # The parameter block: + # XY+ 0 Buffer address for input LSB + # 1 MSB + # 2 Maximum line length + # 3 Minimum acceptable ASCII value + # 4 Maximum acceptable ASCII value + # + # Only characters greater or equal to XY+3 and lesser or equal to + # XY+4 will be accepted. + # + # On exit, C=0 if a carriage return terminated input. + # C=1 if an ESCAPE condition terminated input. + # Y contains line length, including carriage return if + # used. + input_memory = memory.readWord(address) + maxline = memory.readByte(address + 2) + lowest = memory.readByte(address + 3) + highest = memory.readByte(address + 4) + + try: + sys.stdout.flush() + result = self.read_line(maxline, lowest, highest) + result = result[:maxline - 1] + result = result + '\r' + # FIXME: Note that the lowest and highest are not honoured by this + regs.carry = False + regs.Y = len(result) + memory.writeBytes(input_memory, bytearray(result)) + + except EOFError: + raise InputEOFError("EOF received from terminal") + + except KeyboardInterrupt: + regs.carry = True + regs.Y = 0 + + return True + + def read_line(self, maxline, lowest, highest): + """ + Read a line of input; override with any other ReadLine implementation. + """ + return raw_input() + + def osword(self, a, address, regs, memory): + return False diff --git a/console.py b/pybeeb/Host/console.py similarity index 99% rename from console.py rename to pybeeb/Host/console.py index cdb207b..4d5dbe8 100644 --- a/console.py +++ b/pybeeb/Host/console.py @@ -22,7 +22,7 @@ class ConsoleBase(object): _inited = False def __new__(cls, *args, **kwargs): - print("Singleton creation %r" % (cls._singleton)) + #print("Singleton creation %r" % (cls._singleton)) if not cls._singleton: cls._singleton = super(ConsoleBase, cls).__new__(cls, *args, **kwargs) return cls._singleton diff --git a/pybeeb/Host/host.py b/pybeeb/Host/host.py new file mode 100644 index 0000000..10290ff --- /dev/null +++ b/pybeeb/Host/host.py @@ -0,0 +1,78 @@ +""" +Implementations of the OS interfaces which communicate with the host. +""" + +import sys + +from .base import OSInterface, OSWRCH, OSRDCH, OSWORD, InputEOFError +from .console import Console + + +class OSWRCHtty(OSWRCH): + + def writec(self, ch): + if ch == 127: + sys.stdout.write('\x08 \x08') + else: + sys.stdout.write(chr(ch)) + + # Return immediately with an RTS + return True + + +class OSRDCHtty(OSRDCH): + + def __init__(self): + super(OSRDCHtty, self).__init__() + self.console = Console() + + def start(self): + self.console.terminal_init() + + def stop(self): + self.console.terminal_reset() + + def readc(self): + # See: https://mdfs.net/Docs/Comp/BBC/OS1-20/DC1C + #print "OS_RDCH" # Could inject keypresses here maybe? + while True: + ch = self.console.getch() + if ch is not None: + break + if ch == b'': + raise InputEOFError("EOF received from terminal") + return ch + + +class OSWORDtty(OSWORD): + code = 0xE7EB + vector = 0x020C + + def __init__(self): + super(OSWORDtty, self).__init__() + self.console = Console() + + # The dispatch dictionary contains the functions that should be + # dispatched to handle OSBYTE calls. + # The keys in the dictionary may the value of the A register. + # If no matching key exists, the method `osword` will be used. + # The dispatcher used will be called with the parameters + # `(a, address, regs, memory)`. + self.dispatch[0x00] = self.osword_readline + + def read_line(self, maxline, lowest, highest): + """ + Read a line of input; override with any other ReadLine implementation. + """ + + console_active = self.console.terminal_active + if console_active: + self.console.terminal_reset() + + try: + result = raw_input() + finally: + if console_active: + self.console.terminal_init() + + return result From 7b7ceae67a291e7c4b163bd28367fa9839496a88 Mon Sep 17 00:00:00 2001 From: Charles Ferguson Date: Sat, 9 Dec 2023 13:11:59 +0000 Subject: [PATCH 28/65] Add initial support for filesystem interfaces. The filesystem interfaces OSFILE, OSARGS, OSBPUT, OSBGET, OSFIND have been given base implementations which dispatch to different routines. They're not especially well suited to being overridden because each class is independant. Ideally we'd allow a common interface to be provided for the filesystem, which those classes could access. --- PyBeebU.py | 7 +- pybeeb/CPU/Memory.py | 8 + pybeeb/Host/base.py | 551 +++++++++++++++++++++++++++++++++++++++---- pybeeb/Host/host.py | 42 +++- 4 files changed, 562 insertions(+), 46 deletions(-) diff --git a/PyBeebU.py b/PyBeebU.py index 0a1419b..b687d92 100755 --- a/PyBeebU.py +++ b/PyBeebU.py @@ -8,7 +8,7 @@ import sys from pybeeb.PyBeebicorn import Pb, PbError, PbConstants -from pybeeb.Host import BBCError, InputEOFError, OSCLI, OSBYTE, OSInterface +from pybeeb.Host import BBCError, InputEOFError, OSCLI, OSBYTE, OSInterface, OSFILE, OSFIND, OSARGS, OSBPUT, OSBGET from pybeeb.Host.host import OSWRCHtty, OSRDCHtty, OSWORDtty @@ -81,6 +81,11 @@ def mem_hook(pb, access, address, size, value, user_data): OSCLIquit, OSBYTEversion, OSWORDtty, + OSFILE, + OSFIND, + OSARGS, + OSBPUT, + OSBGET, ) try: syscalls = {} diff --git a/pybeeb/CPU/Memory.py b/pybeeb/CPU/Memory.py index 9b49542..d4bb25b 100644 --- a/pybeeb/CPU/Memory.py +++ b/pybeeb/CPU/Memory.py @@ -200,6 +200,14 @@ def readSignedByte(self, address): def readWord(self, address): return self.readByte(address) + (self.readByte(address + 1) << 8) + def readLongWord(self, address): + parts = self.readBytes(address, 4) + return parts[0] | (parts[1]<<8) | (parts[2]<<16) | (parts[3]<<24) + + def writeLongWord(self, address, value): + parts = bytearray([value & 255, (value>>8) & 255, (value>>16) & 255, (value>>24) & 255]) + self.writeBytes(address, value) + def readString(self, address): s = [] while True: diff --git a/pybeeb/Host/base.py b/pybeeb/Host/base.py index 33d9077..f7dc3b9 100644 --- a/pybeeb/Host/base.py +++ b/pybeeb/Host/base.py @@ -13,7 +13,12 @@ 'OSWORD', 'OSCLI', 'OSWRCH', - 'OSRDCH' + 'OSRDCH', + 'OSFILE', + 'OSFIND', + 'OSARGS', + 'OSBPUT', + 'OSBGET', ) @@ -173,14 +178,12 @@ def __init__(self): super(OSWORD, self).__init__() # The dispatch dictionary contains the functions that should be - # dispatched to handle OSBYTE calls. + # dispatched to handle OSWORD calls. # The keys in the dictionary may the value of the A register. # If no matching key exists, the method `osword` will be used. # The dispatcher used will be called with the parameters # `(a, address, regs, memory)`. - self.dispatch = { - 0x00: self.osword_readline, - } + self.dispatch = {} def call(self, regs, memory): dispatcher = self.dispatch.get(regs.a, None) @@ -190,50 +193,514 @@ def call(self, regs, memory): address = regs.x | (regs.y << 8) return dispatcher(regs.a, address, regs, memory) - def osword_readline(self, a, address, regs, memory): - # The parameter block: - # XY+ 0 Buffer address for input LSB - # 1 MSB - # 2 Maximum line length - # 3 Minimum acceptable ASCII value - # 4 Maximum acceptable ASCII value - # - # Only characters greater or equal to XY+3 and lesser or equal to - # XY+4 will be accepted. - # - # On exit, C=0 if a carriage return terminated input. - # C=1 if an ESCAPE condition terminated input. - # Y contains line length, including carriage return if - # used. - input_memory = memory.readWord(address) - maxline = memory.readByte(address + 2) - lowest = memory.readByte(address + 3) - highest = memory.readByte(address + 4) - - try: - sys.stdout.flush() - result = self.read_line(maxline, lowest, highest) - result = result[:maxline - 1] - result = result + '\r' - # FIXME: Note that the lowest and highest are not honoured by this - regs.carry = False - regs.Y = len(result) - memory.writeBytes(input_memory, bytearray(result)) + def osword(self, a, address, regs, memory): + return False - except EOFError: - raise InputEOFError("EOF received from terminal") - except KeyboardInterrupt: +class OSFILE(OSInterface): + code = 0xF27D + vector = 0x0212 + + def __init__(self): + super(OSFILE, self).__init__() + + # The dispatch dictionary contains the functions that should be + # dispatched to handle OSFILE calls. + # The keys in the dictionary may the value of the A register. + # If no matching key exists, the method `osfile` will be used. + # The dispatcher used will be called with the parameters + # `(a, filename, address, regs, memory)`. + self.dispatch = {} + + def call(self, regs, memory): + dispatcher = self.dispatch.get(regs.a, None) + if dispatcher is None: + dispatcher = self.osfile + + address = regs.x | (regs.y << 8) + filename_ptr = memory.readWord(address) + filename = memory.readString(filename_ptr) + return dispatcher(regs.a, filename, address, regs, memory) + + def osfile(self, op, filename, address, regs, memory): + """ + Handle an OSFILE call. + + Memory block contains: + + 00 Address of filename, terminated by RETURN &0D + 01 + 02 Load address of the file. + 03 Low byte first. + 04 + 05 + 06 Execution address of the file. + 07 Low byte first. + 08 + 09 + 0A Start address of data for save, + 0B length of file otherwise. + 0C Low byte first. + 0D + 0E End address of data for save, + 0F file attributes otherwise. + 10 Low byte first. + 11 + + Reason codes in A: + + A=0 Save a block of memory as a file using the information provided in the parameter block. + A=1 Write the information in the parameter block to the catalogue entry for an existing file + (i.e. file name and addresses). + A=2 Write the load address (only) for an existing file. + A=3 Write the execution address (only) for an existing file. + A=4 Write the attributes (only) for an existing file. + A=5 Read a file's catalogue information, with the file type returned in the accumulator. + The information is written to the parameter block. + A=6 Delete the named file. + A=&FF Load the named file, the address to which the file is loaded being determined by the + lowest byte of the execution address in the control block (XY+6). + If this byte is zero, the address given in the controlblock is used, + otherwise the file's own load address is used. + + @param op: operation code from the A register + @param filename: The filename to work with + @param address: The address of the block for file operations + @param regs: Registers + @param memory: Memory access + + @return: True if handled + False if not handled + """ + handled = False + + if op == 0: + # Save + src_address = memory.readLongWord(address + 10) + src_length = memory.readLongWord(address + 14) - src_address + info_load = memory.readLongWord(address + 2) + info_exec = memory.readLongWord(address + 6) + handled = self.save(filename, src_address, src_length, info_load, info_exec, regs, memory) + + elif op == 1: + # Write load+exec+attr + info_load = memory.readLongWord(address + 2) + info_exec = memory.readLongWord(address + 6) + info_attr = memory.readLongWord(address + 14) + handled = self.write_info(filename, info_load, info_exec, info_attr, regs, memory) + + elif op == 2: + # Write load + info_load = memory.readLongWord(address + 2) + handled = self.write_load(filename, info_load, regs, memory) + + elif op == 3: + # Write exec + info_exec = memory.readLongWord(address + 6) + handled = self.write_exec(filename, info_exec, regs, memory) + + elif op == 4: + # Write attr + info_attr = memory.readLongWord(address + 14) + handled = self.write_attr(filename, info_attr, regs, memory) + + elif op == 5: + # Read load+exec+attr + result = self.read_attr(filename, regs, memory) + if result: + handled = True + (info_type, info_load, info_exec, info_length, info_attr) = result + memory.writeLongWord(address + 2, info_load) + memory.writeLongWord(address + 6, info_exec) + memory.writeLongWord(address + 10, info_length) + memory.writeLongWord(address + 14, info_attr) + regs.a = info_type + else: + handled = False + + elif op == 6: + # Delete + handled = self.delete(filename, regs, memory) + + elif op == 255: + # Load + if memory.readByte(address + 6) == 0: + load_address = None + else: + load_address = memory.readLongWord(address + 2) + result = self.load(filename, load_address, regs, memory) + if result: + handled = True + (info_type, info_load, info_exec, info_length, info_attr) = result + memory.writeLongWord(address + 2, info_load) + memory.writeLongWord(address + 6, info_exec) + memory.writeLongWord(address + 10, info_length) + memory.writeLongWord(address + 14, info_attr) + regs.a = info_type + else: + handled = False + + return handled + + def save(self, filename, src_address, src_length, info_load, info_exec, regs, memory): + """ + @param filename: File to operate on + @param src_address: Start address for save + @param src_length: Length of the save + @param info_load: Load address + @param info_exec: Exec address + @param info_attr: File attributes + @param regs: Registers object + @param memory: Memory object + + @return: True if the call is handled, or False if it's not handled + """ + return False + + def write_info(self, filename, info_load, info_exec, info_attr, regs, memory): + """ + @param filename: File to operate on + @param info_load: Load address + @param info_exec: Exec address + @param info_attr: File attributes + @param regs: Registers object + @param memory: Memory object + + @return: True if the call is handled, or False if it's not handled + """ + return False + + def write_load(self, filename, info_load, regs, memory): + """ + @param filename: File to operate on + @param info_load: Load address + @param regs: Registers object + @param memory: Memory object + + @return: True if the call is handled, or False if it's not handled + """ + return False + + def write_exec(self, filename, info_exec, regs, memory): + """ + @param filename: File to operate on + @param info_exec: Exec address + @param regs: Registers object + @param memory: Memory object + + @return: True if the call is handled, or False if it's not handled + """ + return False + + def write_attr(self, filename, info_attr, regs, memory): + """ + @param filename: File to operate on + @param info_attr: File attributes + @param regs: Registers object + @param memory: Memory object + + @return: True if the call is handled, or False if it's not handled + """ + return False + + def read_attr(self, filename, regs, memory): + """ + @param filename: File to operate on + @param info_load: Load address + @param info_exec: Exec address + @param info_attr: File attributes + @param regs: Registers object + @param memory: Memory object + + @return: None if not handled, + Tuple of (info_type, info_load, info_exec, info_length, info_attr) if handled + """ + return None + + def delete(self, filename, regs, memory): + """ + @param filename: File to operate on + @param regs: Registers object + @param memory: Memory object + + @return: True if the call is handled, or False if it's not handled + """ + return False + + def load(self, filename, load_address, regs, memory): + """ + @param filename: File to operate on + @param regs: Registers object + @param memory: Memory object + + @return: None if not handled, + Tuple of (info_type, info_load, info_exec, info_length, info_attr) if handled + """ + return None + + + +class OSARGS(OSInterface): + code = 0xF1E8 + vector = 0x0214 + + def __init__(self): + super(OSARGS, self).__init__() + + # The dispatch dictionary contains the functions that should be + # dispatched to handle OSARGS calls. + # The keys in the dictionary may the value of the A register. + # If no matching key exists, the method `osargs` will be used. + # The dispatcher used will be called with the parameters + # `(a, fh, address, regs, memory)`. + self.dispatch = {} + + def call(self, regs, memory): + dispatcher = self.dispatch.get((regs.a, regs.y), None) + if dispatcher is None: + dispatcher = self.dispatch.get(regs.a, None) + if dispatcher is None: + dispatcher = self.osargs + + fh = regs.y + address = regs.x + return dispatcher(regs.a, fh, address, regs, memory) + + def osargs(self, op, fh, address, regs, memory): + """ + Handle OSARGS call for a given reason code and file handle. + + If fh is 0: + A = 0: Return current filesystem + 1: Return CLI args + 255: Flush all files to storage + else: + A = 0: Return PTR# + 1: Write PTR# + 2: Read EXT# + 255: Flush file to storage + """ + handled = False + if fh == 0: + # Filehandle = 0 + if op == 0x00: + result = self.read_current_filesystem(regs, memory) + handled = result is not None + if handled: + regs.a = result + + elif op == 0x01: + # Read CLI args + result = self.read_cli_args(regs, memory) + handled = result is not None + if handled: + memory.writeLongWord(address, result) + + elif op == 0xFF: + # Flush all files + handled = self.flush_all_files(regs, memory) + + else: + # Filehandle supplied + if op == 0x00: + # Read PTR# + result = self.read_ptr(fh, regs, memory) + handled = result is not None + if handled: + memory.writeLongWord(address, result) + + elif op == 0x01: + # Write PTR# + ptr = memory.readLongWord(address) + handled = self.write_ptr(fh, ptr, regs, memory) + + elif op == 0x02: + # Read EXT# + handled = self.read_ext(fh, regs, memory) + handled = result is not None + if handled: + memory.writeLongWord(address, result) + + elif op == 0xFF: + # Flush file to storage + handled = self.flush_file(fh, regs, memory) + + return False + + def read_ptr(self, fh, regs, memory): + """ + Read PTR#. + + @param fh: File handle to read + @param regs: Registers object + @param memory: Memory object + + @return: PTR for the file, or None if not handled + """ + return None + + def read_ext(self, fh, regs, memory): + """ + Read EXT#. + + @param fh: File handle to read + @param regs: Registers object + @param memory: Memory object + + @return: EXT for the file, or None if not handled + """ + return None + + def write_ptr(self, fh, ptr, regs, memory): + """ + Write PTR#. + + @param fh: File handle to read + @param ptr: New PTR value + @param regs: Registers object + @param memory: Memory object + + @return: True if handled, False if not handled + """ + return None + + def flush_file(self, fh, regs, memory): + """ + Flush file to storage. + + @param fh: File handle to read + @param regs: Registers object + @param memory: Memory object + + @return: True if handled, False if not handled + """ + return False + + def flush_all_files(self, regs, memory): + """ + Flush all files to storage + + @param fh: File handle to read + @param regs: Registers object + @param memory: Memory object + + @return: True if handled, False if not handled + """ + return False + + def read_current_filesystem(self, regs, memory): + """ + Read the current filesystem. + + @param regs: Registers object + @param memory: Memory object + + @return: Filesystem number, or None is not handled + """ + return None + + def read_cli_args(self, regs, memory): + """ + Read the CLI arguments. + + @param regs: Registers object + @param memory: Memory object + + @return: Address of CLI arguments, or None is not handled + """ + return None + + +class OSBGET(OSInterface): + code = 0xF4C9 + vector = 0x0216 + + def call(self, regs, memory): + fh = regs.y + b = self.osbget(fh, regs, memory) + if b is None: + return False + + if b == -1: regs.carry = True - regs.Y = 0 + else: + regs.carry = False + regs.a = b + return True + + def osbget(self, fh, regs, memory): + """ + Handle BGET, returning the byte read. + + @param fh: File handle to read + + @return: byte read, -1 if at file end, or None if not handled + """ + return None + + +class OSBPUT(OSInterface): + code = 0xF529 + vector = 0x0218 + + def call(self, regs, memory): + fh = regs.y + b = regs.a + handled = self.osbput(b, fh, regs, memory) + return handled + def osbput(self, b, fh, regs, memory): + """ + Handle BPUT, writing the supplied byte to a file.. + + @param fh: File handle to write to + @param b: Byte to write + + @return: True if handled, False if not handled. + """ + return False + + +class OSFIND(OSInterface): + code = 0xF3CA + vector = 0x0218 + + def call(self, regs, memory): + a = regs.a + if a == 0: + fh = regs.y + return self.close(fh, regs, memory) + + address = regs.x | (regs.y << 8) + filename_ptr = memory.readWord(address) + filename = memory.readString(filename_ptr) + fh = self.open(a, filename, regs, memory) + if fh is None: + return False + regs.a = fh return True - def read_line(self, maxline, lowest, highest): + def open(self, op, filename, regs, memory): + """ + Open a file for reading, writing or update. + + @param op: operation to perform: + &40: input only + &80: output only + &C0: input and output + @param filename: file to open + + @return: file handle, or 0 if failed to open, or None if not handled """ - Read a line of input; override with any other ReadLine implementation. + print("open(%i, %r)" % (op, filename)) + return None + + def close(self, fh, regs, memory): """ - return raw_input() + Close a previously open file. - def osword(self, a, address, regs, memory): + @param fh: file handle to close, or 0 to close all files. + + @return: True if handled; False if not handled. + """ return False diff --git a/pybeeb/Host/host.py b/pybeeb/Host/host.py index 10290ff..dba72f1 100644 --- a/pybeeb/Host/host.py +++ b/pybeeb/Host/host.py @@ -34,7 +34,6 @@ def stop(self): def readc(self): # See: https://mdfs.net/Docs/Comp/BBC/OS1-20/DC1C - #print "OS_RDCH" # Could inject keypresses here maybe? while True: ch = self.console.getch() if ch is not None: @@ -45,8 +44,6 @@ def readc(self): class OSWORDtty(OSWORD): - code = 0xE7EB - vector = 0x020C def __init__(self): super(OSWORDtty, self).__init__() @@ -60,6 +57,45 @@ def __init__(self): # `(a, address, regs, memory)`. self.dispatch[0x00] = self.osword_readline + def osword_readline(self, a, address, regs, memory): + # The parameter block: + # XY+ 0 Buffer address for input LSB + # 1 MSB + # 2 Maximum line length + # 3 Minimum acceptable ASCII value + # 4 Maximum acceptable ASCII value + # + # Only characters greater or equal to XY+3 and lesser or equal to + # XY+4 will be accepted. + # + # On exit, C=0 if a carriage return terminated input. + # C=1 if an ESCAPE condition terminated input. + # Y contains line length, including carriage return if + # used. + input_memory = memory.readWord(address) + maxline = memory.readByte(address + 2) + lowest = memory.readByte(address + 3) + highest = memory.readByte(address + 4) + + try: + sys.stdout.flush() + result = self.read_line(maxline, lowest, highest) + result = result[:maxline - 1] + result = result + '\r' + # FIXME: Note that the lowest and highest are not honoured by this + regs.carry = False + regs.Y = len(result) + memory.writeBytes(input_memory, bytearray(result)) + + except EOFError: + raise InputEOFError("EOF received from terminal") + + except KeyboardInterrupt: + regs.carry = True + regs.Y = 0 + + return True + def read_line(self, maxline, lowest, highest): """ Read a line of input; override with any other ReadLine implementation. From 710238fa4f4ce97eff6ef97ee0779dc384a2687c Mon Sep 17 00:00:00 2001 From: Charles Ferguson Date: Sat, 9 Dec 2023 16:18:30 +0000 Subject: [PATCH 29/65] Rework the base OS interfaces to be more flexible. The base OS interfaces were duplicating some behaviour and not as common as you might like. The interfaces are a little easier to update now. It's not clear that they're actually going to make for a better general experience but they will allow some more flexibility. Also a few typos fixed. --- PyBeebU.py | 3 +- pybeeb/Host/base.py | 180 ++++++++++++++++++++++++++---------------- pybeeb/PyBeebicorn.py | 4 +- 3 files changed, 115 insertions(+), 72 deletions(-) diff --git a/PyBeebU.py b/PyBeebU.py index b687d92..c2e3c0c 100755 --- a/PyBeebU.py +++ b/PyBeebU.py @@ -1,8 +1,9 @@ #!/usr/bin/env python ''' Created on 12 Oct 2011 +Updated on 09 Dec 2023 -@author: chris.whitworth +@author: chris.whitworth, gerph ''' import sys diff --git a/pybeeb/Host/base.py b/pybeeb/Host/base.py index f7dc3b9..c059782 100644 --- a/pybeeb/Host/base.py +++ b/pybeeb/Host/base.py @@ -1,5 +1,52 @@ """ Base classes for the implementations of host interfaces. + +Each base class is derived from the OSInterface class, which has a standard interface +for handling the entry point. + +The following properties are defined on the object: + +* `code`: The default address of the handler for these entry points, which is usually + stored in the vector entry point. For the file system interfaces, the code + address is for the Tape file system, so *TAPE will reselect these interfaces. +* `vector`: The address of the the vector for this interface. +* `dispatch`: Some objects contain a dispatch table mapping the conditions of the + registers to functions. + This is used by the interfaces which have operation codes in A (and X or Y). +* `dispatch_default`: Default dispatch entry point if none of the `dispatch` mappings + are matched. + +The following methods are defined on the object: + +* `__init__`: creates the interface object. +* `start`: should be called when the system is started and the interface is being + prepared for use. +* `stop`: should be called when the system is destroyed, or the interface is no longer + required. +* `call`: should be called when the OS interface is invoked. It will be passed two + objects - a Registers object, and a Memory object. These may be used to + interact with the emulator system. Returns False to continue execution with + the default handler, or True if the caller should return from the vector (as + if RTS had been executed). + The default `call` method will look up the operation codes using the + `dispatch` map and call to the `dispatch_default` function if none match. +* `dispatch_parameters`: will interpret the registers into a default set of parameters + for the dispatch call. + +Other methods may be provided for individual interfaces to perform specific operations. +Consult the class implementation for more details on these additional methods. + +To provide implementations, a new class should be created based on these base classes. +The child class may provide a new implementation of the `start` and `stop` to initialise +the state of the interface. New implementations may be provided for the `call` method, +or the `dispatch` table can be updated to provide alternative handlers for operation +codes. + +The OSInterface should return the error BBCError to report errors. The caller should +trap these and trigger an error through the BRK mechanism. + +The input system should report InputEOFError if an EOF condition is encountered when +reading input from the user. """ import sys @@ -42,7 +89,23 @@ def __init__(self): """ Initialise the interface. """ - pass + + # The dispatch dictionary contains the functions that should be + # dispatched to handle the OSInterface calls. + # The keys in the dictionary may be one of: + # (A, X, Y) + # (A, X) + # A + # The value of the first matched key will be used as the + # dispatcher. + # If no matching key exists, the method `dispatch_default` will + # be used. + # The dispatcher used will be called with the parameters + # returned by the `dispatch_parameters` method. By default these + # are: + # (A, X, Y, regs, memory) + self.dispatch = {} + self.dispatch_default = None def start(self): """ @@ -56,6 +119,17 @@ def stop(self): """ pass + def dispatch_parameters(self, regs, memory): + """ + Prepare a set of parameters to pass to the dispatcher. + + @param regs: Registers object, containing a, x, y, pc, and sp properties + the flags + @param memory: Memory object, containing the (read|write)(Byte|Bytes|Word|SignedByte) methods + + @return: list of parameters to pass to the dispatcher + """ + return [regs.a, regs.x, regs.y, regs, memory] + def call(self, regs, memory): """ Call the interface with a given set of parameters. @@ -70,6 +144,16 @@ def call(self, regs, memory): @return: True if the call has been handled (return from interface), False if call should continue at the code execution point """ + dispatcher = self.dispatch.get((regs.a, regs.x, regs.y), None) + if dispatcher is None: + dispatcher = self.dispatch.get((regs.a, regs.x), None) + if dispatcher is None: + dispatcher = self.dispatch.get(regs.a, None) + if dispatcher is None: + dispatcher = self.dispatch_default + if dispatcher: + params = self.dispatch_parameters(regs, memory) + return dispatcher(*params) return False @@ -141,30 +225,7 @@ class OSBYTE(OSInterface): def __init__(self): super(OSBYTE, self).__init__() - - # The dispatch dictionary contains the functions that should be - # dispatched to handle OSBYTE calls. - # The keys in the dictionary may be one of: - # (A, X, Y) - # (A, X) - # A - # The value of the first matched key will be used as the - # dispatcher. - # If no matching key exists, the method `osbyte` will be used. - # The dispatcher used will be called with the parameters - # `(A, X, Y, regs, memory)`. - self.dispatch = { - } - - def call(self, regs, memory): - dispatcher = self.dispatch.get((regs.a, regs.x, regs.y), None) - if dispatcher is None: - dispatcher = self.dispatch.get((regs.a, regs.x), None) - if dispatcher is None: - dispatcher = self.dispatch.get(regs.a, None) - if dispatcher is None: - dispatcher = self.osbyte - return dispatcher(regs.a, regs.x, regs.y, regs, memory) + self.dispatch_default = self.osbyte def osbyte(self, a, x, y, regs, memory): return False @@ -177,21 +238,16 @@ class OSWORD(OSInterface): def __init__(self): super(OSWORD, self).__init__() - # The dispatch dictionary contains the functions that should be - # dispatched to handle OSWORD calls. - # The keys in the dictionary may the value of the A register. - # If no matching key exists, the method `osword` will be used. # The dispatcher used will be called with the parameters - # `(a, address, regs, memory)`. - self.dispatch = {} - - def call(self, regs, memory): - dispatcher = self.dispatch.get(regs.a, None) - if dispatcher is None: - dispatcher = self.osword + # (a, address, regs, memory) + self.dispatch_default = self.osword + def dispatch_parameters(self, regs, memory): + """ + Decode the paramters for the address. + """ address = regs.x | (regs.y << 8) - return dispatcher(regs.a, address, regs, memory) + return [regs.a, address, regs, memory] def osword(self, a, address, regs, memory): return False @@ -204,23 +260,15 @@ class OSFILE(OSInterface): def __init__(self): super(OSFILE, self).__init__() - # The dispatch dictionary contains the functions that should be - # dispatched to handle OSFILE calls. - # The keys in the dictionary may the value of the A register. - # If no matching key exists, the method `osfile` will be used. - # The dispatcher used will be called with the parameters - # `(a, filename, address, regs, memory)`. - self.dispatch = {} - - def call(self, regs, memory): - dispatcher = self.dispatch.get(regs.a, None) - if dispatcher is None: - dispatcher = self.osfile + # The default dispatcher is called with: + # (op, filename, address, regs, memory) + self.dispatch_default = self.osfile + def dispatch_parameters(self, regs, memory): address = regs.x | (regs.y << 8) filename_ptr = memory.readWord(address) filename = memory.readString(filename_ptr) - return dispatcher(regs.a, filename, address, regs, memory) + return [regs.a, filename, address, regs, memory] def osfile(self, op, filename, address, regs, memory): """ @@ -439,23 +487,14 @@ def load(self, filename, load_address, regs, memory): return None - class OSARGS(OSInterface): code = 0xF1E8 vector = 0x0214 - def __init__(self): - super(OSARGS, self).__init__() - - # The dispatch dictionary contains the functions that should be - # dispatched to handle OSARGS calls. - # The keys in the dictionary may the value of the A register. - # If no matching key exists, the method `osargs` will be used. - # The dispatcher used will be called with the parameters - # `(a, fh, address, regs, memory)`. - self.dispatch = {} - def call(self, regs, memory): + # NOTE: We do not use the standard dispatcher mechanism here + # because the primary discriminator is the Y register, + # rather than the A register. dispatcher = self.dispatch.get((regs.a, regs.y), None) if dispatcher is None: dispatcher = self.dispatch.get(regs.a, None) @@ -665,13 +704,17 @@ class OSFIND(OSInterface): code = 0xF3CA vector = 0x0218 - def call(self, regs, memory): - a = regs.a - if a == 0: - fh = regs.y - return self.close(fh, regs, memory) + def __init__(self): + super(OSFIND, self).__init__() + # Handle the close dispatch through the dispatch table + self.dispatch[0x00] = self.call_close + self.dispatch_default = self.call_open - address = regs.x | (regs.y << 8) + def call_close(self, a, x, y, regs, memory): + return self.close(fh=y, regs=regs, memory=memory) + + def call_open(self, a, x, y, regs, memory): + address = x | (y << 8) filename_ptr = memory.readWord(address) filename = memory.readString(filename_ptr) fh = self.open(a, filename, regs, memory) @@ -692,7 +735,6 @@ def open(self, op, filename, regs, memory): @return: file handle, or 0 if failed to open, or None if not handled """ - print("open(%i, %r)" % (op, filename)) return None def close(self, fh, regs, memory): diff --git a/pybeeb/PyBeebicorn.py b/pybeeb/PyBeebicorn.py index b886fb4..b0db871 100644 --- a/pybeeb/PyBeebicorn.py +++ b/pybeeb/PyBeebicorn.py @@ -2,7 +2,7 @@ Unicorn-like interface for PyBeeb. Allows code that was written for Unicorn to work with PyBeeb with minimal -modifications (or just reamapping the variable names). +modifications (or just remapping the variable names). """ import os.path @@ -47,8 +47,8 @@ class PbConstants(object): PB_HOOK_MEM_WRITE = 2048 -# access to error code via @errno of UcError class PbError(Exception): + def __init__(self, errno): self.errno = errno From 2204c0aac90622b429608247beaa21616d94847d Mon Sep 17 00:00:00 2001 From: Charles Ferguson Date: Sun, 10 Dec 2023 22:22:40 +0000 Subject: [PATCH 30/65] Initial implementation of OSGBPB. OSGBPB's byte operations are now implemented in a base class. The other GBPB operations that handle the media name, and directory enumeration are not yet implemented. --- PyBeebU.py | 4 +- pybeeb/Host/base.py | 137 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 140 insertions(+), 1 deletion(-) diff --git a/PyBeebU.py b/PyBeebU.py index c2e3c0c..6e32d17 100755 --- a/PyBeebU.py +++ b/PyBeebU.py @@ -9,7 +9,8 @@ import sys from pybeeb.PyBeebicorn import Pb, PbError, PbConstants -from pybeeb.Host import BBCError, InputEOFError, OSCLI, OSBYTE, OSInterface, OSFILE, OSFIND, OSARGS, OSBPUT, OSBGET +from pybeeb.Host import (BBCError, InputEOFError, OSInterface, + OSCLI, OSBYTE, OSFILE, OSFIND, OSARGS, OSBPUT, OSBGET, OSGBPB) from pybeeb.Host.host import OSWRCHtty, OSRDCHtty, OSWORDtty @@ -87,6 +88,7 @@ def mem_hook(pb, access, address, size, value, user_data): OSARGS, OSBPUT, OSBGET, + OSGBPB, ) try: syscalls = {} diff --git a/pybeeb/Host/base.py b/pybeeb/Host/base.py index c059782..a4ff947 100644 --- a/pybeeb/Host/base.py +++ b/pybeeb/Host/base.py @@ -66,6 +66,7 @@ 'OSARGS', 'OSBPUT', 'OSBGET', + 'OSGBPB', ) @@ -746,3 +747,139 @@ def close(self, fh, regs, memory): @return: True if handled; False if not handled. """ return False + + +class OSGBPB(OSInterface): + code = 0xFFA6 + vector = 0x021A + + def __init__(self): + super(OSGBPB, self).__init__() + self.dispatch[0x01] = self.call_put_bytes + self.dispatch[0x02] = self.call_put_bytes + self.dispatch[0x03] = self.call_get_bytes + self.dispatch[0x04] = self.call_get_bytes + self.dispatch_default = self.osgbpb + + def dispatch_parameters(self, regs, memory): + """ + Decode the paramters for the address. + """ + address = regs.x | (regs.y << 8) + return [regs.a, address, regs, memory] + + def osgbpb(self, op, address, regs, memory): + """ + The control block format is: + + 00 File handle + 01 Pointer to data in either I/O processor or Tube + 02 processor. + 03 Low byte first. + 04 + 05 Number of bytes to transfer + 06 Low byte first. + 07 + 08 + 09 Sequential pointer value to be used for transfer + 0A Low byte first. + 0B + 0C + + Operation codes: + + 01 Put bytes at pointer + 02 Put bytes + 03 Get bytes from pointer + 04 Get bytes + 05 Get media title and option + 06 Read CSD and device + 07 Read Lib and device + 08 Read names from CSD + """ + return False + + def call_put_bytes(self, op, address, regs, memory): + """ + Put bytes (at a given location). + """ + fh = memory.readByte(address) + dataaddr = memory.readLongWord(address + 1) + datalen = memory.readLongWord(address + 5) + if op == 1: + ptr = memory.readLongWord(address + 9) + else: + ptr = None + data = memory.readBytes(dataaddr, datalen) + result = self.put_bytes(fh, data, ptr, regs, memory) + if result: + (transferred, newptr) = result + if transferred != datalen: + regs.carry = True + memory.writeLongWord(address + 5, datalen - transferred) + else: + regs.carry = False + memory.writeLongWord(address + 1, dataaddr + transferred) + memory.writeLongWord(address + 9, newptr) + handled = True + else: + handled = False + return handled + + def call_get_bytes(self, op, address, regs, memory): + """ + Put bytes (at a given location). + """ + fh = memory.readByte(address) + dataaddr = memory.readLongWord(address + 1) + datalen = memory.readLongWord(address + 5) + if op == 1: + ptr = memory.readLongWord(address + 9) + else: + ptr = None + result = self.get_bytes(fh, datalen, ptr, regs, memory) + if result: + (data, newptr) = result + transferred = len(data) + if transferred != datalen: + regs.carry = True + memory.writeLongWord(address + 5, datalen - transferred) + else: + regs.carry = False + memory.writeLongWord(address + 1, dataaddr + transferred) + memory.writeLongWord(address + 9, newptr) + memory.writeBytes(dataaddr, data) + handled = True + else: + handled = False + return handled + + def put_bytes(self, fh, data, ptr, regs, memory): + """ + Put bytes to an open file handle. + + @param fh: File handle to read + @param data: Data to write + @param ptr: File pointer to write at, or None to write to current pointer + @param regs: Registers object + @param memory: Memory object + + @return: None if not handled + Tuple of (bytes transferred, new file pointer) + """ + return None + + def get_bytes(self, fh, datalen, ptr, regs, memory): + """ + Get bytes from an open file handle. + + @param fh: File handle to read + @param datalen: Length of data to read + @param ptr: File pointer to read from, or None to read from current pointer + @param regs: Registers object + @param memory: Memory object + + @return: None if not handled + Tuple of (data read, new file pointer) + """ + return None From 50d21d0268894d61ab9f8d6400b5bee39953e87e Mon Sep 17 00:00:00 2001 From: Charles Ferguson Date: Mon, 11 Dec 2023 19:05:22 +0000 Subject: [PATCH 31/65] Allow the cursor key decoding to work when no timeout present. When the timeout is absent, we weren't handling the cursor key decoding. This meant that they came out as escaped VT codes instead of BBC style codes. --- pybeeb/Host/console.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/pybeeb/Host/console.py b/pybeeb/Host/console.py index 4d5dbe8..900a980 100644 --- a/pybeeb/Host/console.py +++ b/pybeeb/Host/console.py @@ -495,7 +495,17 @@ def int_getch(self, timeout=None): ch = None else: - ch = sys.stdin.read(1) + if self.fd is not None: + try: + ch = os.read(self.fd, 1) + except OSError as exc: + # Interrupted system call happens in cases like ctrl-z being pressed. + if exc.errno != errno.EINTR: + raise + ch = None + else: + print(repr(sys.stdin.buffer)) + ch = sys.stdin.read(1) return ch From 818117205843f4a124536d7279b0adac0a24fd86 Mon Sep 17 00:00:00 2001 From: Charles Ferguson Date: Mon, 11 Dec 2023 19:15:33 +0000 Subject: [PATCH 32/65] Initial support for Python 3. Most of the operations have now been updated so that they work with Python 3, allowing us to run the commands safely with Python 3.9 at least. The code still works with Python 2.7 as well. --- PyBeebU.py | 4 +- pybeeb/BBCMicro/OS.py | 2 +- pybeeb/BBCMicro/PagedROM.py | 2 +- pybeeb/CPU/Memory.py | 4 +- pybeeb/CPU/Registers.py | 20 ++-- pybeeb/Host/__init__.py | 2 +- pybeeb/Host/base.py | 8 +- pybeeb/Host/console.py | 191 +++++++++++++++++++----------------- pybeeb/Host/host.py | 7 +- 9 files changed, 126 insertions(+), 114 deletions(-) diff --git a/PyBeebU.py b/PyBeebU.py index 6e32d17..7f0f3f8 100755 --- a/PyBeebU.py +++ b/PyBeebU.py @@ -36,7 +36,7 @@ def go(self, syscalls): class OSCLIquit(OSCLI): def command(self, command, args): - if command == 'QUIT': + if command == b'QUIT': sys.exit() return False @@ -104,7 +104,7 @@ def hook(pb, address, size, user_data, interface=interface): pb.reg.pc = pb.dispatch.pullWord() + 1 except BBCError as exc: pb.memory.writeBytes(0x100, bytearray([0, exc.errnum])) - pb.memory.writeBytes(0x100 + 2, bytearray(exc.errmess)) + pb.memory.writeBytes(0x100 + 2, bytearray(exc.errmess.encode('latin-1'))) pb.reg.pc = 0x100 syscalls[interface.code] = hook diff --git a/pybeeb/BBCMicro/OS.py b/pybeeb/BBCMicro/OS.py index 4f90014..457d4c4 100644 --- a/pybeeb/BBCMicro/OS.py +++ b/pybeeb/BBCMicro/OS.py @@ -1,4 +1,4 @@ -import ROM +from . import ROM BASE = 0xc000 TOP = 0xffff diff --git a/pybeeb/BBCMicro/PagedROM.py b/pybeeb/BBCMicro/PagedROM.py index 7b90960..5a03c48 100644 --- a/pybeeb/BBCMicro/PagedROM.py +++ b/pybeeb/BBCMicro/PagedROM.py @@ -1,4 +1,4 @@ -import ROM +from . import ROM BASE = 0x8000 TOP = 0xbfff diff --git a/pybeeb/CPU/Memory.py b/pybeeb/CPU/Memory.py index d4bb25b..1b2495b 100644 --- a/pybeeb/CPU/Memory.py +++ b/pybeeb/CPU/Memory.py @@ -195,7 +195,9 @@ def writeBytes(self, address, value): def readSignedByte(self, address): b = self.readByte(address) - return unpack("b", chr(b))[0] + if b >= 0x80: + b -= 0x100; + return b def readWord(self, address): return self.readByte(address) + (self.readByte(address + 1) << 8) diff --git a/pybeeb/CPU/Registers.py b/pybeeb/CPU/Registers.py index abcfcb9..1a3bdff 100644 --- a/pybeeb/CPU/Registers.py +++ b/pybeeb/CPU/Registers.py @@ -60,13 +60,13 @@ def reset(self): self.setPS(0) def status(self): - print "%s%s.%s%s%s%s%s" % ( - "N" if self.negative else "-", - "V" if self.overflow else "-", - "B" if self.brk else "-", - "D" if self.dec else "-", - "I" if self.int else "-", - "Z" if self.zero else "-", - "C" if self.carry else "-"), - print "A: %s X: %s Y: %s" % (hex(self.a), hex(self.x), hex(self.y)), - print "PC: %s SP: %s" % (hex(self.pc), hex(self.sp)) + sys.stdout.write("%s%s.%s%s%s%s%s" % ( + "N" if self.negative else "-", + "V" if self.overflow else "-", + "B" if self.brk else "-", + "D" if self.dec else "-", + "I" if self.int else "-", + "Z" if self.zero else "-", + "C" if self.carry else "-")) + sys.stdout.write("A: %s X: %s Y: %s" % (hex(self.a), hex(self.x), hex(self.y))) + sys.stdout.write("PC: %s SP: %s\n" % (hex(self.pc), hex(self.sp))) diff --git a/pybeeb/Host/__init__.py b/pybeeb/Host/__init__.py index 40cd91a..0c822d3 100644 --- a/pybeeb/Host/__init__.py +++ b/pybeeb/Host/__init__.py @@ -2,4 +2,4 @@ Implementations of Interfaces to the BBC MOS which we can trap. """ -from base import * +from .base import * diff --git a/pybeeb/Host/base.py b/pybeeb/Host/base.py index a4ff947..abe9174 100644 --- a/pybeeb/Host/base.py +++ b/pybeeb/Host/base.py @@ -206,13 +206,13 @@ class OSCLI(OSInterface): def call(self, regs, memory): xy = regs.x | (regs.y << 8) cli = memory.readString(xy) - while cli[0] == '*': + while cli[0:1] == b'*': cli = cli[1:] - if ' ' in cli: - (command, args) = cli.split(' ', 1) + if b' ' in cli: + (command, args) = cli.split(b' ', 1) else: command = cli - args = '' + args = b'' return self.command(command.upper(), args) diff --git a/pybeeb/Host/console.py b/pybeeb/Host/console.py index 900a980..f49db1f 100644 --- a/pybeeb/Host/console.py +++ b/pybeeb/Host/console.py @@ -8,7 +8,11 @@ import errno import os -import Queue +try: + import Queue + queue = Queue +except ImportError: + import queue import sys import threading import time @@ -109,72 +113,72 @@ class Console(ConsoleBase): # [24;1~ => [24~ escape_codes = { # Standard sequences - '[A': '\x8F', # Up - '[B': '\x8E', # Down - '[C': '\x8D', # Right - '[D': '\x8C', # Left - '[F': '\x8B', # End (Copy in RISC OS terms) - '[H': '\x1E', # Home - '[Z': '\x09', # Shift-Tab + b'[A': b'\x8F', # Up + b'[B': b'\x8E', # Down + b'[C': b'\x8D', # Right + b'[D': b'\x8C', # Left + b'[F': b'\x8B', # End (Copy in RISC OS terms) + b'[H': b'\x1E', # Home + b'[Z': b'\x09', # Shift-Tab # Application sequences - 'OP': '\x81', # F1 - 'OQ': '\x82', # F2 - 'OR': '\x83', # F3 - 'OS': '\x84', # F4 - 'OH': '\x1E', # Home - 'OF': '\x8B', # End + b'OP': b'\x81', # F1 + b'OQ': b'\x82', # F2 + b'OR': b'\x83', # F3 + b'OS': b'\x84', # F4 + b'OH': b'\x1E', # Home + b'OF': b'\x8B', # End # VT sequences - '[1~': '\x1E', # Home (don't know what this should be) - #'[2~': '\x89', # Insert (don't know what this should be) - '[3~': '\x7F', # Delete - '[4~': '\x8B', # End - '[5~': '\x9F', # Page Up - '[6~': '\x9E', # Page Down - '[7~': '\x1E', # Home - '[8~': '\x87', # End - '[11~': '\x81', # F1 - '[12~': '\x82', # F2 - '[13~': '\x83', # F3 - '[14~': '\x84', # F4 - '[15~': '\x85', # F5 + b'[1~': b'\x1E', # Home (don't know what this should be) + #b'[2~': b'\x89', # Insert (don't know what this should be) + b'[3~': b'\x7F', # Delete + b'[4~': b'\x8B', # End + b'[5~': b'\x9F', # Page Up + b'[6~': b'\x9E', # Page Down + b'[7~': b'\x1E', # Home + b'[8~': b'\x87', # End + b'[11~': b'\x81', # F1 + b'[12~': b'\x82', # F2 + b'[13~': b'\x83', # F3 + b'[14~': b'\x84', # F4 + b'[15~': b'\x85', # F5 # Note 16 isn't mapped - '[17~': '\x86', # F6 - '[18~': '\x87', # F7 - '[19~': '\x88', # F8 - '[20~': '\x89', # F9 - '[21~': '\xCA', # F10 + b'[17~': b'\x86', # F6 + b'[18~': b'\x87', # F7 + b'[19~': b'\x88', # F8 + b'[20~': b'\x89', # F9 + b'[21~': b'\xCA', # F10 # Note 22 isn't mapped - '[23~': '\xCB', # F11 - '[24~': '\xCC', # F12 + b'[23~': b'\xCB', # F11 + b'[24~': b'\xCC', # F12 - '[25~': '\x80', # Print (don't know what this should be) + b'[25~': b'\x80', # Print (don't know what this should be) # Shifted keys - '[1;2P': '\x91', # Shift-F1 - '[1;2Q': '\x92', # Shift-F2 - '[1;2R': '\x93', # Shift-F3 - '[1;2S': '\x94', # Shift-F4 - '[15;2~': '\x95', # Shift-F5 - '[17;2~': '\x96', # Shift-F6 - '[18;2~': '\x97', # Shift-F7 - '[19;2~': '\x98', # Shift-F8 - '[20;2~': '\x99', # Shift-F9 - '[21;2~': '\xDA', # Shift-F10 - '[23;2~': '\xDB', # Shift-F11 - '[24;2~': '\xDC', # Shift-F12 - - '[1;2A': '\x9F', # Shift-Up - '[1;2B': '\x9E', # Shift-Down - '[1;2C': '\x9D', # Shift-Right - '[1;2D': '\x9C', # Shift-Left - '[1;2F': '\x9B', # Shift-End (Copy in RISC OS terms) - '[1;2H': '\x1E', # Shift-Home + b'[1;2P': b'\x91', # Shift-F1 + b'[1;2Q': b'\x92', # Shift-F2 + b'[1;2R': b'\x93', # Shift-F3 + b'[1;2S': b'\x94', # Shift-F4 + b'[15;2~': b'\x95', # Shift-F5 + b'[17;2~': b'\x96', # Shift-F6 + b'[18;2~': b'\x97', # Shift-F7 + b'[19;2~': b'\x98', # Shift-F8 + b'[20;2~': b'\x99', # Shift-F9 + b'[21;2~': b'\xDA', # Shift-F10 + b'[23;2~': b'\xDB', # Shift-F11 + b'[24;2~': b'\xDC', # Shift-F12 + + b'[1;2A': b'\x9F', # Shift-Up + b'[1;2B': b'\x9E', # Shift-Down + b'[1;2C': b'\x9D', # Shift-Right + b'[1;2D': b'\x9C', # Shift-Left + b'[1;2F': b'\x9B', # Shift-End (Copy in RISC OS terms) + b'[1;2H': b'\x1E', # Shift-Home # Ctrled keys - '[1;5H': '\x1E', # Ctrl-Home - '[1;5F': '\xAB', # Ctrl-End (Copy in RISC OS terms) + b'[1;5H': b'\x1E', # Ctrl-Home + b'[1;5F': b'\xAB', # Ctrl-End (Copy in RISC OS terms) } def __init__(self): @@ -231,8 +235,8 @@ def terminal_init(self): new_settings[3] = new_settings[3] | termios.ISIG # Allow a single byte to be read - new_settings[6][termios.VMIN] = '\x01' - new_settings[6][termios.VTIME] = '\x00' + new_settings[6][termios.VMIN] = b'\x01' + new_settings[6][termios.VTIME] = b'\x00' termios.tcsetattr(self.fd, termios.TCSANOW, new_settings) except termios.error as exc: @@ -257,7 +261,7 @@ def parse_utf8(self, seq): """ Parse from a UTF-8 sequence into a sequence that we can insert literally. """ - seq = ''.join(seq) + seq = b''.join(seq) # Decode the sequence from UTF-8 decoded = seq.decode('utf-8', 'replace') if self.debug_inpututf8: @@ -266,36 +270,36 @@ def parse_utf8(self, seq): # Encode the sequence into the current alphabet rostr = self.encode(decoded) if len(rostr) == 1: - return ('\x00', rostr) + return (b'\x00', rostr) else: acc = [] for c in rostr: - acc.extend(('\x00', c)) + acc.extend((b'\x00', c)) return acc def parse_escape(self, seq): - if len(seq) == 0 or (len(seq) == 1 and seq[0] == '\x1b'): + if len(seq) == 0 or (len(seq) == 1 and seq[0] == b'\x1b'): # Literal escape key! # FIXME: Should we set the escape flags here too? - return '\x1b' + return b'\x1b' - if seq[0] == '[': + if seq[0] == b'[': code = seq[-1] - if (code >= 'A' and code <= 'Z') or (code >= 'a' and code <= 'z'): + if (code >= b'A' and code <= b'Z') or (code >= b'a' and code <= b'z'): # letter codes might have numbers preceding them for modifiers. # a modifier of 1 means 'no modifier', so we can strip it - if len(seq) == 3 and seq[1] == '1': + if len(seq) == 3 and seq[1] == b'1': # Reduce it to the un-modifier version so our dictionary is simpler - seq = ['[', code] - elif code == '~': + seq = [b'[', code] + elif code == b'~': # The [;~ sequence can also have a modifier of 1, # so we simplify this as well. - if len(seq) > 3 and seq[-3] == ';' and seq[-2] == '1': + if len(seq) > 3 and seq[-3] == b';' and seq[-2] == b'1': seq = seq[:-3] - seq.append('~') + seq.append(b'~') # FIXME: The modifier might be +1 for Shift, +2 for Alt, +4 for Ctrl - seq = ''.join(seq) + seq = b''.join(seq) value = self.escape_codes.get(seq, None) if self.debug_inputescapes: if value: @@ -317,23 +321,23 @@ def getch(self, timeout=None): if not self.in_escape and not self.in_utf8: now = time.time() ch = self.int_getch(timeout=timeout) - if ch == '\x7F': - ch = chr(self.config.input_backspace_code) - if ch == '\x1b' and self.config.input_escapes: + if ch == b'\x7F': + ch = bytes(bytearray([self.config.input_backspace_code])) + if ch == b'\x1b' and self.config.input_escapes: # This is an escape character, so we're starting a sequence self.in_escape = time.time() self.in_escape_sequence = [] # Work out how much more time we have left until the user's request times out if timeout is not None: timeout -= time.time() - now - elif ch >= '\x80' and self.config.input_utf8: + elif ch >= b'\x80' and self.config.input_utf8: # Likely to be the start of a UTF-8 sequence. - if ch >= '\xc0' and ch <= '\xf7': + if ch >= b'\xc0' and ch <= b'\xf7': # Is a UTF-8 sequence start self.in_utf8_sequence = [ch] - if ch >= '\xf0': + if ch >= b'\xf0': self.in_utf8 = 4 - elif ch >= '\xe0': + elif ch >= b'\xe0': self.in_utf8 = 3 else: self.in_utf8 = 2 @@ -349,7 +353,11 @@ def getch(self, timeout=None): # We know we're in an escape sequence, and we have timeout seconds left. while (timeout is None or timeout > 0) and self.in_escape: now = time.time() - ch = self.int_getch(timeout=timeout if timeout > self.config.input_escapes_timeout else self.config.input_escapes_timeout) + if timeout and timeout > self.config.input_escapes_timeout: + escape_timeout = timeout + else: + escape_timeout = self.config.input_escapes_timeout + ch = self.int_getch(timeout=escape_timeout) if ch is None: break # Escapes end with a ~, A-Z, a-z (or a timeout) @@ -357,18 +365,18 @@ def getch(self, timeout=None): self.in_escape_sequence.append(ch) # In 'application ' mode, some sequences are sent as SS3 followed by a sequence # SS3 => O followed by any character. - if self.in_escape_sequence[0] == 'O': + if self.in_escape_sequence[0] == b'O': if len(self.in_escape_sequence) == 2: # SS3 only applies to the next character. self.in_escape = False break else: - if (ch >= 'A' and ch <= 'Z') or (ch >= 'a' and ch <= 'z') or ch == '~': + if (ch >= b'A' and ch <= b'Z') or (ch >= b'a' and ch <= b'z') or ch == b'~': # This is the end of a sequence self.in_escape = False break - if len(self.in_escape_sequence) == 1 and ch != '[': + if len(self.in_escape_sequence) == 1 and ch != b'[': # This is an sequence self.in_escape = False break @@ -392,16 +400,16 @@ def getch(self, timeout=None): ch = self.int_getch(timeout=timeout) if ch is None: return None - if ch < '\x80' or ch >= '\xc0': + if ch < b'\x80' or ch >= b'\xc0': # This is not a character that should be in the UTF-8 sequence - it's # broken UTF-8. if self.debug_inpututf8: print("Input UTF-8: Invalid sequence %r + %r" % (self.in_utf8_sequence, ch)) # FIXME: Configurable way to handle this? - acc = ''.join(self.in_utf8_sequence) + acc = b''.join(self.in_utf8_sequence) # FIXME: Discard the characters if wanted, or encode? - if ch < '\x80': + if ch < b'\x80': # The excess is a plain character # FIXME: Note that this doesn't handle the excess character being # an escape (!) @@ -412,9 +420,9 @@ def getch(self, timeout=None): # The excess is the start of another UTF-8 sequence, so we # start another sequence self.in_utf8_sequence = [ch] - if ch >= '\xf0': + if ch >= b'\xf0': self.in_utf8 = 4 - elif ch >= '\xe0': + elif ch >= b'\xe0': self.in_utf8 = 3 else: self.in_utf8 = 2 @@ -446,7 +454,7 @@ def is_pending(self, timeout=None): if not input_pending: # And check for new bytes (within the timeout) try: - r, w, x = select.select([sys.stdin], [], [], timeout) + r, w, x = select.select([self.fd], [], [], timeout) if r: input_pending = True except select.error as exc: @@ -463,7 +471,7 @@ def int_getch(self, timeout=None): before = time.time() if self.is_pending(timeout): if self.is_tty: - # Ensures that we avoid Pythons greedy read in the sys.stdin file handle + # Ensures that we avoid Python's greedy read in the sys.stdin file handle # which would otherwise consume more characters, preventing the select # from being aware that the characters are present. try: @@ -475,7 +483,7 @@ def int_getch(self, timeout=None): ch = None else: ch = sys.stdin.read(1) - if ch == '': + if ch == b'': if not self.handle_eof() and timeout is not None: # We didn't do anything, but the handle reported EOF. # We're just going to wait for the timeout period, because otherwise @@ -504,7 +512,6 @@ def int_getch(self, timeout=None): raise ch = None else: - print(repr(sys.stdin.buffer)) ch = sys.stdin.read(1) return ch @@ -552,7 +559,7 @@ def __init__(self): self.thread = None self.alive = True self.want_key = threading.Event() - self.input_queue = Queue.Queue() + self.input_queue = queue.Queue() def finalise(self): if self.thread: diff --git a/pybeeb/Host/host.py b/pybeeb/Host/host.py index dba72f1..c51b084 100644 --- a/pybeeb/Host/host.py +++ b/pybeeb/Host/host.py @@ -85,7 +85,7 @@ def osword_readline(self, a, address, regs, memory): # FIXME: Note that the lowest and highest are not honoured by this regs.carry = False regs.Y = len(result) - memory.writeBytes(input_memory, bytearray(result)) + memory.writeBytes(input_memory, bytearray(result.encode('latin-1'))) except EOFError: raise InputEOFError("EOF received from terminal") @@ -106,7 +106,10 @@ def read_line(self, maxline, lowest, highest): self.console.terminal_reset() try: - result = raw_input() + if sys.version_info.major == 2: + result = raw_input() + else: + result = input() finally: if console_active: self.console.terminal_init() From fe4cd25c221c67b1a3c6cfa2c74ef5ebf2f12fda Mon Sep 17 00:00:00 2001 From: Charles Ferguson Date: Mon, 11 Dec 2023 22:33:21 +0000 Subject: [PATCH 33/65] Add dispatcher for the remaining OSGBPB calls. We now have the dispatcher handling OSGBPB calls for directory names and the reading of filenames. --- pybeeb/Host/base.py | 131 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) diff --git a/pybeeb/Host/base.py b/pybeeb/Host/base.py index abe9174..d99ca56 100644 --- a/pybeeb/Host/base.py +++ b/pybeeb/Host/base.py @@ -759,6 +759,10 @@ def __init__(self): self.dispatch[0x02] = self.call_put_bytes self.dispatch[0x03] = self.call_get_bytes self.dispatch[0x04] = self.call_get_bytes + self.dispatch[0x05] = self.call_get_media_title + self.dispatch[0x06] = lambda op, address, regs, memory: self.call_get_csd_lib(op, address, regs, memory, csd=True) + self.dispatch[0x07] = lambda op, address, regs, memory: self.call_get_csd_lib(op, address, regs, memory, csd=False) + self.dispatch[0x08] = self.call_get_filenames self.dispatch_default = self.osgbpb def dispatch_parameters(self, regs, memory): @@ -854,6 +858,83 @@ def call_get_bytes(self, op, address, regs, memory): handled = False return handled + def call_get_media_title(self, op, address, regs, memory): + """ + Get media title and option as <option> + """ + dataaddr = memory.readLongWord(address + 1) + datalen = memory.readLongWord(address + 5) + result = self.get_media_title(regs, memory) + if result: + (title, option) = result + transferred = 1 + len(title) + 1 + if transferred != datalen: + regs.carry = True + memory.writeLongWord(address + 5, datalen - transferred) + else: + regs.carry = False + data = bytearray([len(title)]) + bytearray(title) + bytearray(option) + memory.writeLongWord(address + 1, dataaddr + transferred) + memory.writeLongWord(address + 9, transferred) + memory.writeBytes(dataaddr, data) + handled = True + else: + handled = False + return handled + + def call_get_csd_lib(self, op, address, regs, memory, csd): + """ + Get CSD/library and device as <len><device><len><csd> + """ + dataaddr = memory.readLongWord(address + 1) + datalen = memory.readLongWord(address + 5) + if csd: + result = self.get_csd(regs, memory) + else: + result = self.get_lib(regs, memory) + if result: + (device, csd) = result + transferred = 1 + len(device) + 1 + len(csd) + if transferred != datalen: + regs.carry = True + memory.writeLongWord(address + 5, datalen - transferred) + else: + regs.carry = False + data = bytearray([len(device)]) + bytearray(device) + bytearray([len(csd)]) + bytearray(csd) + memory.writeLongWord(address + 1, dataaddr + transferred) + memory.writeLongWord(address + 9, transferred) + memory.writeBytes(dataaddr, data) + handled = True + else: + handled = False + return handled + + def call_get_filenames(self, op, address, regs, memory, csd): + """ + Get filenames from the CSD, in form <length><filename>... + """ + dataaddr = memory.readLongWord(address + 1) + nfiles = memory.readLongWord(address + 5) + offset = memory.readLongWord(address + 9) + filenames = self.get_csd_filenames(offset, nfiles, regs, memory) + if filenames is not None: + transferred = len(filenames) + if transferred != nfiles: + regs.carry = True + memory.writeLongWord(address + 5, nfiles - transferred) + else: + regs.carry = False + for filename in filenames: + data = bytearray([len(filename)]) + bytearray(filename) + memory.writeBytes(dataaddr, data) + dataaddr += len(data) + memory.writeLongWord(address + 1, dataaddr) + memory.writeLongWord(address + 9, offset + transferred) + handled = True + else: + handled = False + return handled + def put_bytes(self, fh, data, ptr, regs, memory): """ Put bytes to an open file handle. @@ -883,3 +964,53 @@ def get_bytes(self, fh, datalen, ptr, regs, memory): Tuple of (data read, new file pointer) """ return None + + def get_media_title(self, regs, memory): + """ + Get the media title and boot option + + @param regs: Registers object + @param memory: Memory object + + @return: None if not handled + Tuple of (media title, boot option value) + """ + return None + + def get_csd(self, regs, memory): + """ + Get the device name (eg "0" for disc 0) and CSD + + @param regs: Registers object + @param memory: Memory object + + @return: None if not handled + Tuple of (device name, CSD) + """ + return None + + def get_lib(self, regs, memory): + """ + Get the device name (eg "0" for disc 0) and library + + @param regs: Registers object + @param memory: Memory object + + @return: None if not handled + Tuple of (device name, library directory) + """ + return None + + def get_csd_filenames(self, nfiles, offset, regs, memory): + """ + Get filenames from the CSD. + + @param nfiles: Maximum number of files to read + @param offset: Offset in directory list to start from + @param regs: Registers object + @param memory: Memory object + + @return: None if not handled + List of filenames if handled + """ + return None From f35e493c1715c4deafccadffeb922c6eebc227b5 Mon Sep 17 00:00:00 2001 From: Charles Ferguson <gerph@gerph.org> Date: Tue, 12 Dec 2023 08:12:04 +0000 Subject: [PATCH 34/65] Added base implementation of the OSFSC interface. The OSFSC base implementation is now provided. --- PyBeebU.py | 3 +- pybeeb/Host/base.py | 233 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 234 insertions(+), 2 deletions(-) diff --git a/PyBeebU.py b/PyBeebU.py index 7f0f3f8..d1d4582 100755 --- a/PyBeebU.py +++ b/PyBeebU.py @@ -10,7 +10,7 @@ from pybeeb.PyBeebicorn import Pb, PbError, PbConstants from pybeeb.Host import (BBCError, InputEOFError, OSInterface, - OSCLI, OSBYTE, OSFILE, OSFIND, OSARGS, OSBPUT, OSBGET, OSGBPB) + OSCLI, OSBYTE, OSFILE, OSFIND, OSARGS, OSBPUT, OSBGET, OSGBPB, OSFSC) from pybeeb.Host.host import OSWRCHtty, OSRDCHtty, OSWORDtty @@ -89,6 +89,7 @@ def mem_hook(pb, access, address, size, value, user_data): OSBPUT, OSBGET, OSGBPB, + OSFSC ) try: syscalls = {} diff --git a/pybeeb/Host/base.py b/pybeeb/Host/base.py index d99ca56..fd59c57 100644 --- a/pybeeb/Host/base.py +++ b/pybeeb/Host/base.py @@ -67,6 +67,7 @@ 'OSBPUT', 'OSBGET', 'OSGBPB', + 'OSFSC', ) @@ -767,7 +768,7 @@ def __init__(self): def dispatch_parameters(self, regs, memory): """ - Decode the paramters for the address. + Decode the parameters for the address. """ address = regs.x | (regs.y << 8) return [regs.a, address, regs, memory] @@ -1014,3 +1015,233 @@ def get_csd_filenames(self, nfiles, offset, regs, memory): List of filenames if handled """ return None + + +class OSFSC(OSInterface): + code = 0xFFB1 + vector = 0x021E + + def __init__(self): + super(OSFSC, self).__init__() + self.dispatch[0x00] = self.call_opt + self.dispatch[0x01] = self.call_eof + self.dispatch[0x02] = self.call_slash + self.dispatch[0x03] = self.call_ukcommand + self.dispatch[0x04] = self.call_run + self.dispatch[0x05] = self.call_cat + self.dispatch[0x06] = self.call_fs_starting + self.dispatch[0x07] = self.call_get_handle_range + self.dispatch[0x08] = self.call_star_command + self.dispatch_default = self.osfsc + + def dispatch_parameters(self, regs, memory): + """ + Decode the parameters for the address. + """ + address = regs.x | (regs.y << 8) + return [regs.a, address, regs, memory] + + def osfsc(self, op, address, regs, memory): + """ + Operation codes: + + 00 *OPT X, Y issued + 01 EOF checked on file handle X + 02 */<command> issued + 03 Unrecognised command issued + 04 *RUN <filename> issued + 05 *CAT <directory> issued + 06 New FS starting + 07 Get file handles range in X(low) and Y(high) + 08 *command has been issued + """ + return False + + def call_opt(self, op, address, regs, memory): + """ + *OPT X, Y issued + """ + handled = self.opt(regs.x, regs.y, regs, memory) + return handled + + def call_eof(self, op, address, regs, memory): + """ + EOF check on a file handle. + """ + fh = regs.x + eof = self.eof(fh, regs, memory) + if eof is None: + return False + regs.x = 0xFF if eof else 0x00 + return True + + def call_slash(self, op, address, regs, memory): + """ + A /<command> has been issued + """ + cli = memory.readString(address) + # FIXME: Should we split this up? + handled = self.slash(cli, regs, memory) + return handled + + def call_ukcommand(self, op, address, regs, memory): + """ + An unknown command has been issued + """ + cli = memory.readString(address) + # FIXME: Should we split this up? + handled = self.ukcommand(cli, regs, memory) + return handled + + def call_run(self, op, address, regs, memory): + """ + *Run has been issued + """ + cli = memory.readString(address) + # FIXME: Should we split this up? + handled = self.run(cli, regs, memory) + return handled + + def call_cat(self, op, address, regs, memory): + """ + *Cat has been issued + """ + cat = memory.readString(address) + handled = self.cat(cat, regs, memory) + return handled + + def call_fs_starting(self, op, address, regs, memory): + """ + A new FS is starting up + """ + handled = self.fs_starting(regs, memory) + return handled + + def call_get_handle_range(self, op, address, regs, memory): + """ + Read the range of file handles supported. + """ + result = self.get_handle_range(regs, memory) + if result is None: + return False + (regs.x, regs.y) = result + return True + + def call_star_command(self, op, address, regs, memory): + """ + New *command issued (for handling *Enable) + """ + handled = self.star_command(regs, memory) + return handled + + def opt(self, x, y, regs, memory): + """ + *OPT X, Y issued + + @param x, y: Parameters to *Opt + @param regs: Registers object + @param memory: Memory object + + @return: True if handled, + False if not handled + """ + return False + + def eof(self, fh, regs, memory): + """ + EOF#fh check + + @param fh: + @param regs: Registers object + @param memory: Memory object + + @return: True if EOF, + False if not EOF, + None if not handled + """ + return False + + def slash(self, cli, regs, memory): + """ + */<command> issued. + + @param cli: CLI to execute + @param regs: Registers object + @param memory: Memory object + + @return: True if handled, + False if not handled + """ + return False + + def ukcommand(self, cli, regs, memory): + """ + Unknown command issued + + @param cli: Command issued + @param regs: Registers object + @param memory: Memory object + + @return: True if handled, + False if not handled + """ + return False + + def run(self, run, regs, memory): + """ + *Run issued. + + @param run: Command to run + @param regs: Registers object + @param memory: Memory object + + @return: True if handled, + False if not handled + """ + return False + + def cat(self, dir, regs, memory): + """ + *Cat issued + + @param dir: Directory name + @param regs: Registers object + @param memory: Memory object + + @return: True if handled, + False if not handled + """ + return False + + def fs_starting(self, regs, memory): + """ + New FS is starting. + + @param regs: Registers object + @param memory: Memory object + + @return: True if handled, + False if not handled + """ + return False + + def get_handle_range(self, regs, memory): + """ + @param regs: Registers object + @param memory: Memory object + + @return: None if not handled + Tuple of (low handle, high handle) if handled + """ + return False + + def star_command(self, regs, memory): + """ + @param regs: Registers object + @param memory: Memory object + + @return: True if handled, + False if not handled + """ + return False + From ee17e652a0ec28d0e1bd28af56c744893f2e40a2 Mon Sep 17 00:00:00 2001 From: Charles Ferguson <gerph@gerph.org> Date: Sat, 16 Dec 2023 13:05:00 +0000 Subject: [PATCH 35/65] Add rudimetary host filesystem module and implementation of load/save. We now have a host filesystem module, fsbbc.py, which provides a BBC-like interface to the host filesystem. It's not tested beyond being run through a few simple exercises, but the name translation is based on code from RISC OS Pyromaniac so it should have the right style of thing in it. The OSFILE load and OSFILE save operations are implemented and these allow BASIC to load files and save them. --- PyBeebU.py | 19 +- pybeeb/CPU/Memory.py | 2 +- pybeeb/Host/base.py | 4 +- pybeeb/Host/fsbbc.py | 596 ++++++++++++++++++++++++++++++++++++++++++ pybeeb/Host/hostfs.py | 144 ++++++++++ 5 files changed, 753 insertions(+), 12 deletions(-) create mode 100644 pybeeb/Host/fsbbc.py create mode 100644 pybeeb/Host/hostfs.py diff --git a/PyBeebU.py b/PyBeebU.py index d1d4582..5a2404d 100755 --- a/PyBeebU.py +++ b/PyBeebU.py @@ -12,6 +12,7 @@ from pybeeb.Host import (BBCError, InputEOFError, OSInterface, OSCLI, OSBYTE, OSFILE, OSFIND, OSARGS, OSBPUT, OSBGET, OSGBPB, OSFSC) from pybeeb.Host.host import OSWRCHtty, OSRDCHtty, OSWORDtty +from pybeeb.Host.hostfs import host_fs_interfaces class BBC(object): @@ -77,20 +78,20 @@ def mem_hook(pb, access, address, size, value, user_data): # Report memory reads and writes anywhere between the PAGE and HIMEM (video memory). #bbc.pb.hook_add(PbConstants.PB_HOOK_MEM_READ | PbConstants.PB_HOOK_MEM_WRITE, mem_hook, begin=0xe00, end=0x7c00) - interface_classes = ( + interface_classes = [ OSWRCHtty, OSRDCHtty, OSCLIquit, OSBYTEversion, OSWORDtty, - OSFILE, - OSFIND, - OSARGS, - OSBPUT, - OSBGET, - OSGBPB, - OSFSC - ) + #OSFILE, + #OSFIND, + #OSARGS, + #OSBPUT, + #OSBGET, + #OSGBPB, + #OSFSC + ] + host_fs_interfaces('.') try: syscalls = {} interfaces = [] diff --git a/pybeeb/CPU/Memory.py b/pybeeb/CPU/Memory.py index 1b2495b..29c8db5 100644 --- a/pybeeb/CPU/Memory.py +++ b/pybeeb/CPU/Memory.py @@ -208,7 +208,7 @@ def readLongWord(self, address): def writeLongWord(self, address, value): parts = bytearray([value & 255, (value>>8) & 255, (value>>16) & 255, (value>>24) & 255]) - self.writeBytes(address, value) + self.writeBytes(address, parts) def readString(self, address): s = [] diff --git a/pybeeb/Host/base.py b/pybeeb/Host/base.py index fd59c57..e9e6e9b 100644 --- a/pybeeb/Host/base.py +++ b/pybeeb/Host/base.py @@ -375,9 +375,9 @@ def osfile(self, op, filename, address, regs, memory): elif op == 255: # Load if memory.readByte(address + 6) == 0: - load_address = None - else: load_address = memory.readLongWord(address + 2) + else: + load_address = None result = self.load(filename, load_address, regs, memory) if result: handled = True diff --git a/pybeeb/Host/fsbbc.py b/pybeeb/Host/fsbbc.py new file mode 100644 index 0000000..a5b4de8 --- /dev/null +++ b/pybeeb/Host/fsbbc.py @@ -0,0 +1,596 @@ +""" +Interfaces to the host filesystem. +""" + +import os +import stat +import sys + +from .base import BBCError + +open_in = 0x40 +open_out = 0x80 +open_up = 0xC0 +open_mask = 0xC0 + + +class BBCFileNotFoundError(BBCError): + pass + + +class BBCNoHandlesError(BBCError): + pass + + +class BBCBadHandleError(BBCError): + pass + + +class DirectoryEntry(object): + default_loadaddr = 0x00000000 + default_execaddr = 0x00000000 + default_attributes = 0b00110011 + hexdigits = '0123456789abcdef' + + stat_read_mask = stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH + stat_write_mask = stat.S_IWUSR | stat.S_IWGRP | stat.S_IWOTH + + def __init__(self, fs, native_name, parent): + self.fs = fs + self.native_name = native_name or '' + self.name = native_name + self.parent = parent + + self.loadaddr = self.default_loadaddr + self.execaddr = self.default_execaddr + self.attributes = self.default_attributes + + if native_name != '$': + name = self.fs.decode_from_filesystem(native_name) + explicit_loadexec = False + if len(name) > 18 and \ + name[-9] == ',' and name[-18] == ',' and \ + all(c in self.hexdigits for c in name[-8:]) and \ + all(c in self.hexdigits for c in name[-17:-9]): + # 1+8+1+8 for ,llllllll,eeeeeeee + self.loadaddr = int(name[-17:-9], 16) + self.execaddr = int(name[-8:], 16) + name = name[:-18] + explicit_loadexec = True + + if not explicit_loadexec: + # The filename wasn't using explicit load and exec. + # Let's see if we can infer anything. + ext = None + #print("Checking name %r" % (name,)) + if len(name) > 4 and \ + name[-4] == ',' and all(c in self.hexdigits for c in name[-3:]): + ext = name[-4:] + + elif len(name) > 4 and \ + name[-4] == '/': + # The name has already been decoded from the filesystem, so . => /. + ext = '.' + name[-3:] + + if ext: + loadexec = self.fs.loadexec_from_extension.get(ext, None) + #print("Lookup for %r: extension %r gave %r" % (self.native_name, ext, loadexec)) + if loadexec: + (self.loadaddr, self.execaddr) = loadexec + name = name[:-len(ext)] + + self.name = name + self.fullpath_native = None + if parent is not None: + self.fullpath_native = os.path.join(parent.fullpath_native, native_name) + + try: + st = os.stat(self.fullpath_native) + except OSError: + self.objtype = 0 + self.loadaddr = 0 + self.execaddr = 0 + self.size = 0 + self.attributes = 0 + else: + self.objtype = 1 + mode = st.st_mode + if stat.S_ISDIR(mode): + self.objtype = 2 + self.size = 0 + else: + self.size = st.st_size + + # Determine attributes + self.extract_attributes(st) + + else: + # When we don't know the filetype, we leave it set to 0 + if native_name == '$': + # This is the root entry, so fake as a directory + self.objtype = 2 + else: + self.objtype = 0 + + def __repr__(self): + return "<DirectoryEntry(%r/%r, %i, &%08x, &%08x, %i, &%x)>" \ + % (self.name, self.native_name, + self.objtype, self.loadaddr, self.execaddr, self.size, self.attributes) + + def extract_attributes(self, st): + """ + Extract the attributes from the native file. + + @param st: stat information for the file + """ + mode = st.st_mode + uid = self.fs.native_uid + if uid is None: + return + + # Only apply the file attributes if we have some UID determinable + rval = mode & self.stat_read_mask + if rval == self.stat_read_mask: + # Definitely readable + self.attributes |= 0x11 + elif rval == 0: + # Definitely not readable + self.attributes &= ~0x11 + else: + # Determine from UID/GID + self.attributes &= ~0x11 + #print("R name=%s uid=%i/%i mode=%o" % (self.name, st.st_uid, uid, mode)) + if st.st_uid == uid: + # We are the user, so check permissions for USR + if mode & stat.S_IRUSR: + self.attributes |= 0x1 + if mode & stat.S_IRGRP or mode & stat.S_IROTH: + self.attributes |= 0x10 + + elif st.st_gid in self.fs.native_gids: + # We are in the group, so check permissions for GRP + if mode & stat.S_IRGRP: + self.attributes |= 0x1 + if mode & stat.S_IROTH: + self.attributes |= 0x10 + + else: + if mode & stat.S_IROTH: + self.attributes |= 0x11 + + rval = mode & self.stat_write_mask + if rval == self.stat_write_mask: + # Definitely writable + self.attributes |= 0x22 + elif rval == 0: + # Definitely not writable + self.attributes &= ~0x22 + else: + # Determine from UID/GID + #print("W name=%s uid=%i/%i mode=%o" % (self.name, st.st_uid, uid, mode)) + self.attributes &= ~0x22 + if st.st_uid == uid: + # We are the user, so check permissions for USR + if mode & stat.S_IWUSR: + self.attributes |= 0x2 + if mode & stat.S_IWGRP or mode & stat.S_IWOTH: + self.attributes |= 0x20 + + elif st.st_gid in self.fs.native_gids: + # We are in the group, so check permissions for GRP + if mode & stat.S_IWGRP: + self.attributes |= 0x2 + if mode & stat.S_IWOTH: + self.attributes |= 0x20 + + else: + if mode & stat.S_IWOTH: + self.attributes |= 0x22 + + def generate_native_filename(self, name=None, loadaddr=None, execaddr=None): + """ + Work out what the native filename should be for this file if the name + or the load/exec changed + """ + if not name: + name = self.name + if loadaddr is None: + loadaddr = self.loadaddr + if execaddr is None: + execaddr = self.execaddr + + new_name = self.fs.generate_native_filename(name, loadaddr, execaddr, self.objtype) + + return new_name + + +class Directory(object): + + def __init__(self, fs, name, parent): + self.fs = fs + self.name = name + self.fullpath = self.fs.join(parent, name) + if parent: + self.fullpath_native = os.path.join(parent.fullpath_native, name) + else: + self.fullpath_native = self.fs.basedir + self._files = None + + @property + def files(self): + if not self._files: + filenames = os.listdir(self.fullpath_native) + + files = {} + #print("Files in %r" % (self.fullpath,)) + for filename in filenames: + dirent = DirectoryEntry(fs=self.fs, native_name=filename, parent=self) + files[dirent.name.lower()] = dirent + #print(" %r" % (dirent,)) + self._files = files + return self._files + + def invalidate(self): + self._files = None + + def __getitem__(self, name): + """ + Find a file in this directory. + """ + dirent = self.files.get(name.lower(), None) + if dirent is None: + # FIXME: Find the error number + raise BBCFileNotFoundError(0, "File '%s' not found" % (name,)) + return dirent + + +class OpenFile(object): + howmap = { + open_in: 'rb', + open_out: 'wb', + open_up: 'w+b', + } + + def __init__(self, fs, dirent, how): + self.fs = fs + self.handle = 0 + self.dirent = dirent + self.how = how & open_mask + self.openhow = self.howmap[self.how] + + self.fh = open(dirent.fullpath_native, self.openhow) + + def __repr__(self): + return "<{}(how={})>".format(self.__class__.__name__, self.openhow) + + def close(self): + self.fh.close() + self.fh = None + + def ptr(self, ptr=None): + if ptr is None: + return self.fh.tell() + self.fh.seek(ptr, os.SEEK_SET) + + def ext(self): + ptr = self.ptr() + self.fh.seek(ptr, os.SEEK_END) + ext = self.ptr() + self.ptr(ptr) + return ext + + def read(self, size): + data = self.fh.read(size) + return data + + def write(self, data): + self.fh.write(data) + + def eof(self, handle): + ptr = self.ptr() + self.fh.seek(ptr, os.SEEK_END) + ext = self.ptr() + self.ptr(ptr) + return ptr == ext + + +class FS(object): + """ + An interface for accessing the filesystem. + """ + loadexec_to_extension = { + (None, 0xFFFF8023): '.bas', + (None, 0xFFFF801F): '.bas', + (0xFFFF8000, 0xFFFF8000): '.rom', + (0xFFFFFFFF, 0xFFFFFFFF): '.txt', + } + loadexec_from_extension = { + '.bas': (0xFFFF0E00, 0xFFFF8023), + '.rom': (0xFFFF8000, 0xFFFF8000), + '.txt': (0xFFFFFFFF, 0xFFFFFFFF), + + # NFS style RISC OS extensions + ',ffb': (0xFFFF0E00, 0xFFFF8023), # Tokenised BBC BASIC + ',fd1': (0xFFFFFFFF, 0xFFFFFFFF), # Detokenised BBC BASIC + ',fff': (0xFFFFFFFF, 0xFFFFFFFF), # Text + '.bbc': (0xFFFF8000, 0xFFFF8000), # BBC ROM + } + + open_loadaddr = 0xFFFFFFFF + open_execaddr = 0xFFFFFFFF + + def __init__(self, basedir="."): + self.basedir = basedir + self.cached = {} + self.filehandles = {} + self._next_filehandle = 255 + + try: + self.native_uid = os.getuid() + self.native_gids = set(os.getgroups()) + except Exception: + # If we cannot read them, then set the uid to None to allow us to bypass checks + self.native_uid = None + self.native_gids = set([]) + + def encode_to_filesystem(self, filename): + """ + Convert from a unicode string to something in the host filesystem. + """ + + # FIXME: Perform some conversion on the character set + + # In the filesystem a '/' is reported as a '.' + filename = filename.replace('/', '.') + + return filename + + def decode_from_filesystem(self, filename): + """ + Convert from a host filesystem name to a unicode string for BBC. + """ + + # FIXME: Perform some conversion on the character set + + # In the filesystem a '/' is reported as a '.' + filename = filename.replace('.', '/') + + return filename + + def join(self, *paths): + parts = ['$'] + for path in paths: + if path is None or path == '$': + parts = ['$'] + else: + parts.append(path) + if '^' in parts: + # Only go through the process of reconciling '^' if one was present + return self.canonicalise('.'.join(parts)) + return '.'.join(parts) + + def generate_native_filename(self, name, loadaddr, execaddr, objtype): + """ + Work out what the native filename should be for this file if the name + or the load/exec changed + """ + + # Do the basic conversion + new_name = self.encode_to_filesystem(name) + + if objtype == 2: + return new_name + + # Certain load/exec extensions are able to be converted through the mapping + ext = self.loadexec_to_extension.get((loadaddr, execaddr), None) + if not ext: + ext = self.loadexec_to_extension.get((loadaddr, None), None) + if not ext: + ext = self.loadexec_to_extension.get((None, execaddr), None) + if ext: + new_name = "%s%s" % (new_name, ext) + else: + # Load and exec address are required, so we need to put the long extension on + # Ensure the load and exec are the unsigned values: + if loadaddr < 0: + loadaddr += (1<<32) + loadaddr = loadaddr & 0xFFFFFFFF + if execaddr < 0: + execaddr += (1<<32) + execaddr = execaddr & 0xFFFFFFFF + + new_name = '%s,%08x,%08x' % (new_name, loadaddr, execaddr) + + return new_name + + def split(self, path): + parts = ['$'] + for part in path.split('.'): + if part == '$': + parts = ['$'] + elif part == '^': + if len(parts) > 1: + parts = parts[:-1] + else: + parts.append(part) + return parts + + def canonicalise(self, path): + parts = self.split(path) + return '.'.join(parts) + + def dirname(self, path): + parts = self.split(path) + if parts: + parts = parts[:-1] + return self.join(parts) + + def leafname(self, path): + parts = self.split(path) + return parts[-1] + + def splitname(self, path): + parts = self.split(path) + dirname = '.'.join(parts[:-1]) + if not dirname: + dirname = "$" + leafname = parts[-1] + return (dirname, leafname) + + def dir(self, path): + path = self.canonicalise(path) + #print("dir(%s)" % (path,)) + dir = self.cached.get(path.lower(), None) + if dir is None: + (dirname, leafname) = self.splitname(path) + #print(" dirname=%s leafname=%s" % (dirname, leafname)) + if dirname != '$': + parent = self.dir(dirname) + dir = Directory(self, leafname, parent) + else: + dir = Directory(self, leafname, None) + + self.cached[path.lower()] = dir + return dir + + def find(self, path): + (dirname, leafname) = self.splitname(path) + dir = self.dir(dirname) + dirent = dir[leafname] + return dirent + + def allocate_filehandle(self, bfh): + if not self._next_filehandle: + # FIXME: Fix error number + raise BBCNoHandlesError(0, "No more file handles") + + bfh.handle = self._next_filehandle + self.filehandles[bfh.handle] = bfh + while self._next_filehandle != 0: + self._next_filehandle -= 1 + if self._next_filehandle not in self.filehandles: + break + + if self._next_filehandle == 0: + # We got to the end and there weren't any handles. Start again + self._next_filehandle = 256 + while self._next_filehandle != 0: + self._next_filehandle -= 1 + if self._next_filehandle not in self.filehandles: + break + # IF there were none left, we'll run out of handles here and end up with the next one being 0 + + def release_filehandle(self, handle): + del self.filehandles[handle] + if handle > self._next_filehandle: + self._next_filehandle = handle + # If the handle one higher is also free, the next handle can be that one. + while handle < 255: + handle += 1 + if handle not in self.filehandles: + self._next_filehandle = handle + else: + break + + def find_handle(self, handle): + bfh = self.filehandles.get(handle, None) + if not bfh: + # FIXME: Fix error number + raise BBCBadHandleError(0, "Bad file handle") + return bfh + + def ensure_exists(self, path, loadaddr, execaddr): + """ + Ensure a file exists, creating it if needed, renaming if not. + """ + (dirname, leafname) = self.splitname(path) + dir = self.dir(dirname) + + try: + dirent = dir[leafname] + except BBCFileNotFoundError: + # If the file isn't there, we need to create one. + native_leafname = self.generate_native_filename(leafname, loadaddr, execaddr, 1) + native_path = os.path.join(dir.fullpath_native, native_leafname) + # Create the file + with open(native_path, 'w') as fh: + pass + dir.invalidate() + dirent = dir[leafname] + + # Now check that the load and exec are consistent + if dirent.loadaddr != loadaddr or dirent.execaddr != execaddr: + # The name of the file in the directory doesn't match, so we need to generate a new name + # This should only really happen if the file we want already exists + native_leafname = self.generate_native_filename(leafname, loadaddr, execaddr, 1) + if native_leafname != dirent.native_name: + native_path = os.path.join(dir.fullpath_native, native_leafname) + os.rename(dirent.fullpath_native, native_path) + + def fileinfo(self, filename): + dirent = self.find(filename) + info_type = dirent.objtype + info_load = dirent.loadaddr + info_exec = dirent.execaddr + info_length = dirent.size + info_attr = dirent.attributes + return (info_type, info_load, info_exec, info_length, info_attr) + + def set_fileinfo(self, filename, loadaddr, execaddr, attr): + # Check that it exists before we apply the set_fileinfo. + dirent = self.find(filename) + + # Ensure exists will perform any rename that we need to make the file exist with those attributes + self.ensure_exists(filename, loadaddr, execaddr) + + if dirent.attributes != attr: + # FIXME: attributes aren't affected yet + pass + + def open(self, filename, how): + try: + dirent = self.find(filename) + except BBCFileNotFoundError as exc: + if (how & open_mask) == open_in: + # Reading the file, so the file has to exist. + raise + + # Writing, or updating, so we want to create the file first + self.ensure_exists(filename, self.open_loadaddr, self.open_execaddr) + + bfh = OpenFile(self, dirent, how) + self.allocate_filehandle(bfh) + return bfh.handle + + def close(self, handle): + if handle == 0: + # FIXME: Could make this work as on the BBC + raise BBCError(0, "Not closing all files") + + bfh = self.find_handle(handle) + bfh.close() + self.release_filehandle(handle) + + def ptr_seek(self, handle, ptr): + bfh = self.find_handle(handle) + return bfh.ptr(ptr) + + def ptr_read(self, handle): + bfh = self.find_handle(handle) + return bfh.ptr() + + def ext_read(self, handle): + bfh = self.find_handle(handle) + return bfh.ext() + + def read(self, handle, size): + bfh = self.find_handle(handle) + return bfh.read(size) + + def write(self, handle, data): + bfh = self.find_handle(handle) + return bfh.write(data) + + def eof(self, handle): + bfh = self.find_handle(handle) + return bfh.eof() diff --git a/pybeeb/Host/hostfs.py b/pybeeb/Host/hostfs.py new file mode 100644 index 0000000..41a095d --- /dev/null +++ b/pybeeb/Host/hostfs.py @@ -0,0 +1,144 @@ +""" +Implementations of the OS interfaces which communicate with the host (file system specific) +""" + +from .base import OSInterface, OSFILE, BBCError +from .fsbbc import FS, BBCFileNotFoundError, open_in, open_out + + +class OSFILEhost(OSFILE): + + def __init__(self, fs): + super(OSFILEhost, self).__init__() + self.fs = fs + + def save(self, filename, src_address, src_length, info_load, info_exec, regs, memory): + """ + @param filename: File to operate on + @param src_address: Start address for save + @param src_length: Length of the save + @param info_load: Load address + @param info_exec: Exec address + @param info_attr: File attributes + @param regs: Registers object + @param memory: Memory object + + @return: True if the call is handled, or False if it's not handled + """ + self.fs.ensure_exists(filename, info_load, info_exec) + handle = self.fs.open(filename, open_out) + data = memory.readBytes(src_address & 0xFFFF, src_length) + self.fs.write(handle, data) + return True + + def write_info(self, filename, info_load, info_exec, info_attr, regs, memory): + """ + @param filename: File to operate on + @param info_load: Load address + @param info_exec: Exec address + @param info_attr: File attributes + @param regs: Registers object + @param memory: Memory object + + @return: True if the call is handled, or False if it's not handled + """ + return False + + def write_load(self, filename, info_load, regs, memory): + """ + @param filename: File to operate on + @param info_load: Load address + @param regs: Registers object + @param memory: Memory object + + @return: True if the call is handled, or False if it's not handled + """ + return False + + def write_exec(self, filename, info_exec, regs, memory): + """ + @param filename: File to operate on + @param info_exec: Exec address + @param regs: Registers object + @param memory: Memory object + + @return: True if the call is handled, or False if it's not handled + """ + return False + + def write_attr(self, filename, info_attr, regs, memory): + """ + @param filename: File to operate on + @param info_attr: File attributes + @param regs: Registers object + @param memory: Memory object + + @return: True if the call is handled, or False if it's not handled + """ + return False + + def read_attr(self, filename, regs, memory): + """ + @param filename: File to operate on + @param info_load: Load address + @param info_exec: Exec address + @param info_attr: File attributes + @param regs: Registers object + @param memory: Memory object + + @return: None if not handled, + Tuple of (info_type, info_load, info_exec, info_length, info_attr) if handled + """ + return None + + def delete(self, filename, regs, memory): + """ + @param filename: File to operate on + @param regs: Registers object + @param memory: Memory object + + @return: True if the call is handled, or False if it's not handled + """ + return False + + def load(self, filename, load_address, regs, memory): + """ + @param filename: File to operate on + @param regs: Registers object + @param memory: Memory object + + @return: None if not handled, + Tuple of (info_type, info_load, info_exec, info_length, info_attr) if handled + """ + handle = None + try: + (info_type, info_load, info_exec, info_length, info_attr) = self.fs.fileinfo(filename) + if info_type == 0: + # FIXME: Error number + raise BBCFileNotFoundError(0, "File not found") + if info_type == 2: + # FIXME: Error number + raise BBCFileNotFoundError(0, "Is a directory") + + if load_address is None: + load_address = info_load & 0xFFFF + + handle = self.fs.open(filename, open_in) + size = self.fs.ext_read(handle) + data = self.fs.read(handle, size) + memory.writeBytes(load_address & 0xFFFF, data) + finally: + if handle: + self.fs.close(handle) + + return (info_type, info_load, info_exec, info_length, info_attr) + + +def host_fs_interfaces(basedir): + """ + Construct a list of OS interfaces for filesystems, using a host base directory. + """ + fs = FS(basedir) + return [ + lambda: OSFILEhost(fs) + ] From 88aa90349d405ed962923879e52cc137e6d23ae5 Mon Sep 17 00:00:00 2001 From: Charles Ferguson <gerph@gerph.org> Date: Mon, 18 Dec 2023 01:53:02 +0000 Subject: [PATCH 36/65] Implement remaining OSFILE interfaces for host filesystem. We now have the read/write file information and their variants, and the delete operation, implemented in the host filesystem version of OSFILE. --- pybeeb/Host/base.py | 4 ++-- pybeeb/Host/fsbbc.py | 7 +++++++ pybeeb/Host/hostfs.py | 23 ++++++++++++++++------- 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/pybeeb/Host/base.py b/pybeeb/Host/base.py index e9e6e9b..5020882 100644 --- a/pybeeb/Host/base.py +++ b/pybeeb/Host/base.py @@ -356,7 +356,7 @@ def osfile(self, op, filename, address, regs, memory): elif op == 5: # Read load+exec+attr - result = self.read_attr(filename, regs, memory) + result = self.read_info(filename, regs, memory) if result: handled = True (info_type, info_load, info_exec, info_length, info_attr) = result @@ -453,7 +453,7 @@ def write_attr(self, filename, info_attr, regs, memory): """ return False - def read_attr(self, filename, regs, memory): + def read_info(self, filename, regs, memory): """ @param filename: File to operate on @param info_load: Load address diff --git a/pybeeb/Host/fsbbc.py b/pybeeb/Host/fsbbc.py index a5b4de8..1088242 100644 --- a/pybeeb/Host/fsbbc.py +++ b/pybeeb/Host/fsbbc.py @@ -547,6 +547,13 @@ def set_fileinfo(self, filename, loadaddr, execaddr, attr): # FIXME: attributes aren't affected yet pass + def delete(self, filename): + dirent = self.find(filename) + if dirent.objtype == 1: + os.unlink(dirent.fullpath_native) + else: + os.rmdir(dirent.fullpath_native) + def open(self, filename, how): try: dirent = self.find(filename) diff --git a/pybeeb/Host/hostfs.py b/pybeeb/Host/hostfs.py index 41a095d..2da688e 100644 --- a/pybeeb/Host/hostfs.py +++ b/pybeeb/Host/hostfs.py @@ -42,7 +42,8 @@ def write_info(self, filename, info_load, info_exec, info_attr, regs, memory): @return: True if the call is handled, or False if it's not handled """ - return False + self.fs.set_fileinfo(filename, info_load, info_exec, info_attr) + return True def write_load(self, filename, info_load, regs, memory): """ @@ -53,7 +54,9 @@ def write_load(self, filename, info_load, regs, memory): @return: True if the call is handled, or False if it's not handled """ - return False + (info_type, _, info_exec, info_length, info_attr) = self.fs.fileinfo(filename) + self.fs.set_fileinfo(filename, info_load, info_exec, info_attr) + return True def write_exec(self, filename, info_exec, regs, memory): """ @@ -64,7 +67,9 @@ def write_exec(self, filename, info_exec, regs, memory): @return: True if the call is handled, or False if it's not handled """ - return False + (info_type, info_load, _, info_length, info_attr) = self.fs.fileinfo(filename) + self.fs.set_fileinfo(filename, info_load, info_exec, info_attr) + return True def write_attr(self, filename, info_attr, regs, memory): """ @@ -75,9 +80,11 @@ def write_attr(self, filename, info_attr, regs, memory): @return: True if the call is handled, or False if it's not handled """ - return False + (info_type, info_load, info_exec, info_length, _) = self.fs.fileinfo(filename) + self.fs.set_fileinfo(filename, info_load, info_exec, info_attr) + return True - def read_attr(self, filename, regs, memory): + def read_info(self, filename, regs, memory): """ @param filename: File to operate on @param info_load: Load address @@ -89,7 +96,8 @@ def read_attr(self, filename, regs, memory): @return: None if not handled, Tuple of (info_type, info_load, info_exec, info_length, info_attr) if handled """ - return None + (info_type, info_load, info_exec, info_length, info_attr) = self.fs.fileinfo(filename) + return (info_type, info_load, info_exec, info_length, info_attr) def delete(self, filename, regs, memory): """ @@ -99,7 +107,8 @@ def delete(self, filename, regs, memory): @return: True if the call is handled, or False if it's not handled """ - return False + self.fs.delete(filename) + return True def load(self, filename, load_address, regs, memory): """ From 587abc60bbd1e7a78678af45d4a1ad440d801e3b Mon Sep 17 00:00:00 2001 From: Charles Ferguson <gerph@gerph.org> Date: Mon, 18 Dec 2023 02:34:17 +0000 Subject: [PATCH 37/65] Add simple implementation of host stream open and output. OSFIND, OSBGET and OSBPUT are now implemented. This should hopefully do the right thing for us, although they're not well tested. --- pybeeb/Host/base.py | 3 +- pybeeb/Host/fsbbc.py | 7 ++++ pybeeb/Host/hostfs.py | 85 ++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 91 insertions(+), 4 deletions(-) diff --git a/pybeeb/Host/base.py b/pybeeb/Host/base.py index 5020882..db1a9bc 100644 --- a/pybeeb/Host/base.py +++ b/pybeeb/Host/base.py @@ -716,8 +716,7 @@ def call_close(self, a, x, y, regs, memory): return self.close(fh=y, regs=regs, memory=memory) def call_open(self, a, x, y, regs, memory): - address = x | (y << 8) - filename_ptr = memory.readWord(address) + filename_ptr = x | (y << 8) filename = memory.readString(filename_ptr) fh = self.open(a, filename, regs, memory) if fh is None: diff --git a/pybeeb/Host/fsbbc.py b/pybeeb/Host/fsbbc.py index 1088242..016cdc0 100644 --- a/pybeeb/Host/fsbbc.py +++ b/pybeeb/Host/fsbbc.py @@ -258,6 +258,7 @@ def __init__(self, fs, dirent, how): self.how = how & open_mask self.openhow = self.howmap[self.how] + #print("OpenFile(dirent=%r, how=%r): openhow=%r" % (dirent, how, self.openhow)) self.fh = open(dirent.fullpath_native, self.openhow) def __repr__(self): @@ -388,6 +389,7 @@ def generate_native_filename(self, name, loadaddr, execaddr, objtype): if not ext: ext = self.loadexec_to_extension.get((None, execaddr), None) if ext: + #print("ext name : %s / %s" % (new_name, ext)) new_name = "%s%s" % (new_name, ext) else: # Load and exec address are required, so we need to put the long extension on @@ -510,8 +512,10 @@ def ensure_exists(self, path, loadaddr, execaddr): dirent = dir[leafname] except BBCFileNotFoundError: # If the file isn't there, we need to create one. + #print("Try to create new file for %r : %r / %r" % (path, dirname, leafname)) native_leafname = self.generate_native_filename(leafname, loadaddr, execaddr, 1) native_path = os.path.join(dir.fullpath_native, native_leafname) + #print("Native name = %r" % (native_path,)) # Create the file with open(native_path, 'w') as fh: pass @@ -558,12 +562,15 @@ def open(self, filename, how): try: dirent = self.find(filename) except BBCFileNotFoundError as exc: + #print("Not found (%s), how=%r" % (filename, how)) if (how & open_mask) == open_in: # Reading the file, so the file has to exist. raise # Writing, or updating, so we want to create the file first + #print(" ensure exists") self.ensure_exists(filename, self.open_loadaddr, self.open_execaddr) + dirent = self.find(filename) bfh = OpenFile(self, dirent, how) self.allocate_filehandle(bfh) diff --git a/pybeeb/Host/hostfs.py b/pybeeb/Host/hostfs.py index 2da688e..c63a50d 100644 --- a/pybeeb/Host/hostfs.py +++ b/pybeeb/Host/hostfs.py @@ -2,7 +2,7 @@ Implementations of the OS interfaces which communicate with the host (file system specific) """ -from .base import OSInterface, OSFILE, BBCError +from .base import OSInterface, OSFILE, OSFIND, OSBGET, OSBPUT, BBCError from .fsbbc import FS, BBCFileNotFoundError, open_in, open_out @@ -143,11 +143,92 @@ def load(self, filename, load_address, regs, memory): return (info_type, info_load, info_exec, info_length, info_attr) +class OSFINDhost(OSFIND): + + def __init__(self, fs): + super(OSFINDhost, self).__init__() + self.fs = fs + + def open(self, op, filename, regs, memory): + """ + Open a file for reading, writing or update. + + @param op: operation to perform: + &40: input only + &80: output only + &C0: input and output + @param filename: file to open + + @return: file handle, or 0 if failed to open, or None if not handled + """ + try: + handle = self.fs.open(filename, op) + except BBCFileNotFoundError as exc: + handle = 0 + + return handle + + def close(self, fh, regs, memory): + """ + Close a previously open file. + + @param fh: file handle to close, or 0 to close all files. + + @return: True if handled; False if not handled. + """ + self.fs.close(fh) + return True + + +class OSBGEThost(OSBGET): + + def __init__(self, fs): + super(OSBGEThost, self).__init__() + self.fs = fs + + def osbget(self, fh, regs, memory): + """ + Handle BGET, returning the byte read. + + @param fh: File handle to read + + @return: byte read, -1 if at file end, or None if not handled + """ + data = self.fs.read(fh, 1) + if not data: + return -1 + return data[0] + + +class OSBPUThost(OSBPUT): + + def __init__(self, fs): + super(OSBPUThost, self).__init__() + self.fs = fs + + def osbput(self, b, fh, regs, memory): + """ + Handle BPUT, writing the supplied byte to a file.. + + @param fh: File handle to write to + @param b: Byte to write + + @return: True if handled, False if not handled. + """ + #print("bput %r" % (b,)) + data = bytes(bytearray([b])) + self.fs.write(fh, data) + return True + + def host_fs_interfaces(basedir): """ Construct a list of OS interfaces for filesystems, using a host base directory. """ fs = FS(basedir) return [ - lambda: OSFILEhost(fs) + lambda: OSFILEhost(fs), + lambda: OSFINDhost(fs), + lambda: OSBGEThost(fs), + lambda: OSBPUThost(fs), ] From 046a41be172465e8a74d9f42a61056130222b4c8 Mon Sep 17 00:00:00 2001 From: Charles Ferguson <gerph@gerph.org> Date: Mon, 18 Dec 2023 16:53:25 +0000 Subject: [PATCH 38/65] Fix for incorrect data mode for ADC indexed Y access. The data mode for ADC indexed Y access was listed as `imy` instead of `iny`. --- pybeeb/insts.csv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pybeeb/insts.csv b/pybeeb/insts.csv index b53239f..b77d5d5 100644 --- a/pybeeb/insts.csv +++ b/pybeeb/insts.csv @@ -112,7 +112,7 @@ hex,instr,addr,wb,len,tim 6E,ROR,abs,M,3,6 6F,,,,, 70,BVS,rel,PC,2,2 -71,ADC,imy,A,2,5 +71,ADC,iny,A,2,5 72,,,,, 73,,,,, 74,,,,, From 73ff73405cf3f06abf6ef54b5aa47b1f3374ea32 Mon Sep 17 00:00:00 2001 From: Charles Ferguson <gerph@gerph.org> Date: Mon, 18 Dec 2023 16:56:53 +0000 Subject: [PATCH 39/65] Add simple implementation of the OSARGS calls. We now implement some of the stream handling in OSARGS, allowing us to manipulate the pointer. --- pybeeb/Host/fsbbc.py | 22 +++++++--- pybeeb/Host/hostfs.py | 99 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 114 insertions(+), 7 deletions(-) diff --git a/pybeeb/Host/fsbbc.py b/pybeeb/Host/fsbbc.py index 016cdc0..3ac0e3c 100644 --- a/pybeeb/Host/fsbbc.py +++ b/pybeeb/Host/fsbbc.py @@ -209,7 +209,12 @@ class Directory(object): def __init__(self, fs, name, parent): self.fs = fs self.name = name - self.fullpath = self.fs.join(parent, name) + #print("Creating directory %s, parent %r" % (name, parent)) + if parent: + self.fullpath = self.fs.join(parent.fullpath, name) + else: + self.fullpath = self.fs.join("$", name) + if parent: self.fullpath_native = os.path.join(parent.fullpath_native, name) else: @@ -222,7 +227,7 @@ def files(self): filenames = os.listdir(self.fullpath_native) files = {} - #print("Files in %r" % (self.fullpath,)) + #print("Files in %r (%r)" % (self.fullpath, self.fullpath_native)) for filename in filenames: dirent = DirectoryEntry(fs=self.fs, native_name=filename, parent=self) files[dirent.name.lower()] = dirent @@ -287,7 +292,10 @@ def read(self, size): def write(self, data): self.fh.write(data) - def eof(self, handle): + def flush(self): + self.fh.flush() + + def eof(self): ptr = self.ptr() self.fh.seek(ptr, os.SEEK_END) ext = self.ptr() @@ -446,7 +454,7 @@ def dir(self, path): if dir is None: (dirname, leafname) = self.splitname(path) #print(" dirname=%s leafname=%s" % (dirname, leafname)) - if dirname != '$': + if leafname != '$': parent = self.dir(dirname) dir = Directory(self, leafname, parent) else: @@ -585,7 +593,7 @@ def close(self, handle): bfh.close() self.release_filehandle(handle) - def ptr_seek(self, handle, ptr): + def ptr_write(self, handle, ptr): bfh = self.find_handle(handle) return bfh.ptr(ptr) @@ -597,6 +605,10 @@ def ext_read(self, handle): bfh = self.find_handle(handle) return bfh.ext() + def flush(self, handle): + bfh = self.find_handle(handle) + bfh.flush() + def read(self, handle, size): bfh = self.find_handle(handle) return bfh.read(size) diff --git a/pybeeb/Host/hostfs.py b/pybeeb/Host/hostfs.py index c63a50d..09d6cd5 100644 --- a/pybeeb/Host/hostfs.py +++ b/pybeeb/Host/hostfs.py @@ -2,7 +2,7 @@ Implementations of the OS interfaces which communicate with the host (file system specific) """ -from .base import OSInterface, OSFILE, OSFIND, OSBGET, OSBPUT, BBCError +from .base import OSInterface, OSFILE, OSFIND, OSBGET, OSBPUT, OSARGS, BBCError from .fsbbc import FS, BBCFileNotFoundError, open_in, open_out @@ -197,7 +197,7 @@ def osbget(self, fh, regs, memory): data = self.fs.read(fh, 1) if not data: return -1 - return data[0] + return bytearray(data[0])[0] class OSBPUThost(OSBPUT): @@ -221,6 +221,100 @@ def osbput(self, b, fh, regs, memory): return True +class OSARGShost(OSARGS): + + def __init__(self, fs): + super(OSARGShost, self).__init__() + self.fs = fs + + def read_ptr(self, fh, regs, memory): + """ + Read PTR#. + + @param fh: File handle to read + @param regs: Registers object + @param memory: Memory object + + @return: PTR for the file, or None if not handled + """ + ptr = self.fs.ptr_read(fh) + return ptr + + def read_ext(self, fh, regs, memory): + """ + Read EXT#. + + @param fh: File handle to read + @param regs: Registers object + @param memory: Memory object + + @return: EXT for the file, or None if not handled + """ + ext = self.fs.ext_read(fh) + return ext + + def write_ptr(self, fh, ptr, regs, memory): + """ + Write PTR#. + + @param fh: File handle to read + @param ptr: New PTR value + @param regs: Registers object + @param memory: Memory object + + @return: True if handled, False if not handled + """ + self.fs.ptr_write(fh, ptr) + return True + + def flush_file(self, fh, regs, memory): + """ + Flush file to storage. + + @param fh: File handle to read + @param regs: Registers object + @param memory: Memory object + + @return: True if handled, False if not handled + """ + self.fs.flush(fh) + return True + + def flush_all_files(self, regs, memory): + """ + Flush all files to storage + + @param fh: File handle to read + @param regs: Registers object + @param memory: Memory object + + @return: True if handled, False if not handled + """ + return False + + def read_current_filesystem(self, regs, memory): + """ + Read the current filesystem. + + @param regs: Registers object + @param memory: Memory object + + @return: Filesystem number, or None is not handled + """ + return 4 # FS_DFS + + def read_cli_args(self, regs, memory): + """ + Read the CLI arguments. + + @param regs: Registers object + @param memory: Memory object + + @return: Address of CLI arguments, or None is not handled + """ + return None + + def host_fs_interfaces(basedir): """ Construct a list of OS interfaces for filesystems, using a host base directory. @@ -231,4 +325,5 @@ def host_fs_interfaces(basedir): lambda: OSFINDhost(fs), lambda: OSBGEThost(fs), lambda: OSBPUThost(fs), + lambda: OSARGShost(fs), ] From 2bcfd52456dd86fb15f382b40a335a99a1f9b267 Mon Sep 17 00:00:00 2001 From: Charles Ferguson <gerph@gerph.org> Date: Tue, 19 Dec 2023 02:01:59 +0000 Subject: [PATCH 40/65] Update Makefile to clean away .pyc files. The .pyc files can be cleaned away to make them get rebuilt. Useful if we're changing content. --- Makefile | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index cbd4e8c..857b477 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,9 @@ -# Run our tests +# Manage operations on the repository. + +run: coverage + +clean: + find . -name '*.pyc' -delete coverage_clear: ./coverage_run.py --clear From 6f366a8d561695c5de48dbfd0a1f3f0c96e35c2f Mon Sep 17 00:00:00 2001 From: Charles Ferguson <gerph@gerph.org> Date: Tue, 19 Dec 2023 02:04:15 +0000 Subject: [PATCH 41/65] Move host.py to hosttty.py. The hosttty.py file is there to operate only on the TTY, so we might as well name it as such. --- PyBeebU.py | 2 +- pybeeb/Host/{host.py => hosttty.py} | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename pybeeb/Host/{host.py => hosttty.py} (99%) diff --git a/PyBeebU.py b/PyBeebU.py index 5a2404d..f085040 100755 --- a/PyBeebU.py +++ b/PyBeebU.py @@ -11,7 +11,7 @@ from pybeeb.PyBeebicorn import Pb, PbError, PbConstants from pybeeb.Host import (BBCError, InputEOFError, OSInterface, OSCLI, OSBYTE, OSFILE, OSFIND, OSARGS, OSBPUT, OSBGET, OSGBPB, OSFSC) -from pybeeb.Host.host import OSWRCHtty, OSRDCHtty, OSWORDtty +from pybeeb.Host.hosttty import OSWRCHtty, OSRDCHtty, OSWORDtty from pybeeb.Host.hostfs import host_fs_interfaces diff --git a/pybeeb/Host/host.py b/pybeeb/Host/hosttty.py similarity index 99% rename from pybeeb/Host/host.py rename to pybeeb/Host/hosttty.py index c51b084..7cce248 100644 --- a/pybeeb/Host/host.py +++ b/pybeeb/Host/hosttty.py @@ -1,5 +1,5 @@ """ -Implementations of the OS interfaces which communicate with the host. +Implementations of the OS interfaces which communicate with the host for input and output. """ import sys From f9391ca85be6b913e7a84ad05e6f82772e1ecce6 Mon Sep 17 00:00:00 2001 From: Charles Ferguson <gerph@gerph.org> Date: Tue, 19 Dec 2023 02:33:05 +0000 Subject: [PATCH 42/65] Add hosttty support for INKEY(+ve). Reading a key within a time limit is now supported by the INKEY OSBYTE call. --- PyBeebU.py | 5 +++- pybeeb/Host/console.py | 64 ++++++++++++++++++++++-------------------- pybeeb/Host/hosttty.py | 51 +++++++++++++++++++++++++++++++-- 3 files changed, 85 insertions(+), 35 deletions(-) diff --git a/PyBeebU.py b/PyBeebU.py index f085040..ed7d0dd 100755 --- a/PyBeebU.py +++ b/PyBeebU.py @@ -11,7 +11,7 @@ from pybeeb.PyBeebicorn import Pb, PbError, PbConstants from pybeeb.Host import (BBCError, InputEOFError, OSInterface, OSCLI, OSBYTE, OSFILE, OSFIND, OSARGS, OSBPUT, OSBGET, OSGBPB, OSFSC) -from pybeeb.Host.hosttty import OSWRCHtty, OSRDCHtty, OSWORDtty +from pybeeb.Host.hosttty import OSWRCHtty, OSRDCHtty, OSWORDtty, OSBYTEtty from pybeeb.Host.hostfs import host_fs_interfaces @@ -84,6 +84,7 @@ def mem_hook(pb, access, address, size, value, user_data): OSCLIquit, OSBYTEversion, OSWORDtty, + OSBYTEtty, #OSFILE, #OSFIND, #OSARGS, @@ -101,7 +102,9 @@ def mem_hook(pb, access, address, size, value, user_data): interfaces.append(interface) def hook(pb, address, size, user_data, interface=interface): try: + #print("Call interface %r" % (interface,)) handled = interface.call(pb.reg, pb.memory) + #print(" handled = %r" % (handled,)) if handled: pb.reg.pc = pb.dispatch.pullWord() + 1 except BBCError as exc: diff --git a/pybeeb/Host/console.py b/pybeeb/Host/console.py index f49db1f..7fdb67c 100644 --- a/pybeeb/Host/console.py +++ b/pybeeb/Host/console.py @@ -214,47 +214,49 @@ def get_isatty(self): return False def terminal_init(self): - if not self.is_dead: - self.fd = self.get_fd() - self.is_tty = self.get_isatty() + if not self.terminal_active: + if not self.is_dead: + self.fd = self.get_fd() + self.is_tty = self.get_isatty() - if self.is_tty: - try: - # Preserve old settings - self.old_settings = termios.tcgetattr(self.fd) + if self.is_tty: + try: + # Preserve old settings + self.old_settings = termios.tcgetattr(self.fd) - # Set up our requirements - tty.setraw(self.fd, termios.TCSANOW) - new_settings = termios.tcgetattr(self.fd) + # Set up our requirements + tty.setraw(self.fd, termios.TCSANOW) + new_settings = termios.tcgetattr(self.fd) - # Output post processing (LF => CR, LF mostly) only if requested - if self.cooked_newlines: - new_settings[1] = new_settings[1] | termios.OPOST | termios.ONLCR + # Output post processing (LF => CR, LF mostly) only if requested + if self.cooked_newlines: + new_settings[1] = new_settings[1] | termios.OPOST | termios.ONLCR - # Allow interrupt signals - new_settings[3] = new_settings[3] | termios.ISIG + # Allow interrupt signals + new_settings[3] = new_settings[3] | termios.ISIG - # Allow a single byte to be read - new_settings[6][termios.VMIN] = b'\x01' - new_settings[6][termios.VTIME] = b'\x00' + # Allow a single byte to be read + new_settings[6][termios.VMIN] = b'\x01' + new_settings[6][termios.VTIME] = b'\x00' - termios.tcsetattr(self.fd, termios.TCSANOW, new_settings) - except termios.error as exc: - if exc.args[0] == errno.EIO: - self.is_dead = True - self.is_tty = False - else: - raise - if not self.cooked_newlines: - sys.stdout = self + termios.tcsetattr(self.fd, termios.TCSANOW, new_settings) + except termios.error as exc: + if exc.args[0] == errno.EIO: + self.is_dead = True + self.is_tty = False + else: + raise + if not self.cooked_newlines: + sys.stdout = self super(Console, self).terminal_init() def terminal_reset(self): - if self.is_tty: - termios.tcsetattr(self.fd, termios.TCSADRAIN, self.old_settings) - if not self.cooked_newlines: - sys.stdout = self.original_stdout + if self.terminal_active: + if self.is_tty: + termios.tcsetattr(self.fd, termios.TCSADRAIN, self.old_settings) + if not self.cooked_newlines: + sys.stdout = self.original_stdout super(Console, self).terminal_reset() def parse_utf8(self, seq): diff --git a/pybeeb/Host/hosttty.py b/pybeeb/Host/hosttty.py index 7cce248..f8cde8e 100644 --- a/pybeeb/Host/hosttty.py +++ b/pybeeb/Host/hosttty.py @@ -4,7 +4,7 @@ import sys -from .base import OSInterface, OSWRCH, OSRDCH, OSWORD, InputEOFError +from .base import OSInterface, OSWRCH, OSRDCH, OSWORD, OSBYTE, InputEOFError from .console import Console @@ -43,6 +43,51 @@ def readc(self): return ch +class OSBYTEtty(OSBYTE): + + def __init__(self): + super(OSBYTEtty, self).__init__() + self.console = Console() + + self.dispatch[0x81] = self.inkey + + def start(self): + self.console.terminal_init() + + def stop(self): + self.console.terminal_reset() + + def inkey(self, a, x, y, regs, memory): + if y == 0xFF and x == 0: + # Read machine type + return False + if y == 0xFF and x >= 0x80: + # Keyboard scan + return False + + delay_cs = x | (y<<8) + + ch = self.console.getch(delay_cs / 100.0) + + if ch == b'': + raise InputEOFError("EOF received from terminal") + + if ch is not None: + # If a character is detected, X=ASCII value of key pressed, Y=0 and C=0. + regs.x = ord(ch) + regs.y = 0 + regs.carry = False + else: + # If a character is not detected within timeout then Y=&FF and C=1. + regs.y = 0xff + regs.carry = False + if ch == b'\x1b': + # If Escape is pressed then Y=&1B (27) and C=1. + regs.carry = True + + return True + + class OSWORDtty(OSWORD): def __init__(self): @@ -84,7 +129,7 @@ def osword_readline(self, a, address, regs, memory): result = result + '\r' # FIXME: Note that the lowest and highest are not honoured by this regs.carry = False - regs.Y = len(result) + regs.y = len(result) memory.writeBytes(input_memory, bytearray(result.encode('latin-1'))) except EOFError: @@ -92,7 +137,7 @@ def osword_readline(self, a, address, regs, memory): except KeyboardInterrupt: regs.carry = True - regs.Y = 0 + regs.y = 0 return True From dca76584a10b1a8e4cd8ff1c2adc661853093014 Mon Sep 17 00:00:00 2001 From: Charles Ferguson <gerph@gerph.org> Date: Tue, 19 Dec 2023 19:06:30 +0000 Subject: [PATCH 43/65] Add support for EOF to host FS implementation. The EOF check now works, either when called through OSFSC or OSBYTE. --- pybeeb/Host/fsbbc.py | 28 ++++---- pybeeb/Host/hostfs.py | 146 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 161 insertions(+), 13 deletions(-) diff --git a/pybeeb/Host/fsbbc.py b/pybeeb/Host/fsbbc.py index 3ac0e3c..f72b664 100644 --- a/pybeeb/Host/fsbbc.py +++ b/pybeeb/Host/fsbbc.py @@ -327,12 +327,13 @@ class FS(object): open_loadaddr = 0xFFFFFFFF open_execaddr = 0xFFFFFFFF + filehandle_max = 255 def __init__(self, basedir="."): self.basedir = basedir self.cached = {} self.filehandles = {} - self._next_filehandle = 255 + self._next_filehandle = self.filehandle_max try: self.native_uid = os.getuid() @@ -483,7 +484,7 @@ def allocate_filehandle(self, bfh): if self._next_filehandle == 0: # We got to the end and there weren't any handles. Start again - self._next_filehandle = 256 + self._next_filehandle = self.filehandle_max + 1 while self._next_filehandle != 0: self._next_filehandle -= 1 if self._next_filehandle not in self.filehandles: @@ -495,20 +496,23 @@ def release_filehandle(self, handle): if handle > self._next_filehandle: self._next_filehandle = handle # If the handle one higher is also free, the next handle can be that one. - while handle < 255: + while handle < self.filehandle_max: handle += 1 if handle not in self.filehandles: self._next_filehandle = handle else: break - def find_handle(self, handle): + def find_filehandle(self, handle): bfh = self.filehandles.get(handle, None) if not bfh: # FIXME: Fix error number raise BBCBadHandleError(0, "Bad file handle") return bfh + def filehandle_range(self): + return (1, self.filehandle_max) + def ensure_exists(self, path, loadaddr, execaddr): """ Ensure a file exists, creating it if needed, renaming if not. @@ -589,34 +593,34 @@ def close(self, handle): # FIXME: Could make this work as on the BBC raise BBCError(0, "Not closing all files") - bfh = self.find_handle(handle) + bfh = self.find_filehandle(handle) bfh.close() self.release_filehandle(handle) def ptr_write(self, handle, ptr): - bfh = self.find_handle(handle) + bfh = self.find_filehandle(handle) return bfh.ptr(ptr) def ptr_read(self, handle): - bfh = self.find_handle(handle) + bfh = self.find_filehandle(handle) return bfh.ptr() def ext_read(self, handle): - bfh = self.find_handle(handle) + bfh = self.find_filehandle(handle) return bfh.ext() def flush(self, handle): - bfh = self.find_handle(handle) + bfh = self.find_filehandle(handle) bfh.flush() def read(self, handle, size): - bfh = self.find_handle(handle) + bfh = self.find_filehandle(handle) return bfh.read(size) def write(self, handle, data): - bfh = self.find_handle(handle) + bfh = self.find_filehandle(handle) return bfh.write(data) def eof(self, handle): - bfh = self.find_handle(handle) + bfh = self.find_filehandle(handle) return bfh.eof() diff --git a/pybeeb/Host/hostfs.py b/pybeeb/Host/hostfs.py index 09d6cd5..4842060 100644 --- a/pybeeb/Host/hostfs.py +++ b/pybeeb/Host/hostfs.py @@ -2,7 +2,7 @@ Implementations of the OS interfaces which communicate with the host (file system specific) """ -from .base import OSInterface, OSFILE, OSFIND, OSBGET, OSBPUT, OSARGS, BBCError +from .base import OSInterface, OSFILE, OSFIND, OSBGET, OSBPUT, OSARGS, OSFSC, OSBYTE, BBCError from .fsbbc import FS, BBCFileNotFoundError, open_in, open_out @@ -315,6 +315,148 @@ def read_cli_args(self, regs, memory): return None +class OSFSChost(OSFSC): + + def __init__(self, fs): + super(OSFSChost, self).__init__() + self.fs = fs + + def dispatch_parameters(self, regs, memory): + """ + Decode the parameters for the address. + """ + address = regs.x | (regs.y << 8) + return [regs.a, address, regs, memory] + + def opt(self, x, y, regs, memory): + """ + *OPT X, Y issued + + @param x, y: Parameters to *Opt + @param regs: Registers object + @param memory: Memory object + + @return: True if handled, + False if not handled + """ + return False + + def eof(self, fh, regs, memory): + """ + EOF#fh check + + @param fh: + @param regs: Registers object + @param memory: Memory object + + @return: True if EOF, + False if not EOF, + None if not handled + """ + return self.fs.eof(fh) + + def slash(self, cli, regs, memory): + """ + */<command> issued. + + @param cli: CLI to execute + @param regs: Registers object + @param memory: Memory object + + @return: True if handled, + False if not handled + """ + return False + + def ukcommand(self, cli, regs, memory): + """ + Unknown command issued + + @param cli: Command issued + @param regs: Registers object + @param memory: Memory object + + @return: True if handled, + False if not handled + """ + return False + + def run(self, run, regs, memory): + """ + *Run issued. + + @param run: Command to run + @param regs: Registers object + @param memory: Memory object + + @return: True if handled, + False if not handled + """ + return False + + def cat(self, dir, regs, memory): + """ + *Cat issued + + @param dir: Directory name + @param regs: Registers object + @param memory: Memory object + + @return: True if handled, + False if not handled + """ + return False + + def fs_starting(self, regs, memory): + """ + New FS is starting. + + @param regs: Registers object + @param memory: Memory object + + @return: True if handled, + False if not handled + """ + return False + + def get_handle_range(self, regs, memory): + """ + @param regs: Registers object + @param memory: Memory object + + @return: None if not handled + Tuple of (low handle, high handle) if handled + """ + return self.fs.handle_range() + + def star_command(self, regs, memory): + """ + @param regs: Registers object + @param memory: Memory object + + @return: True if handled, + False if not handled + """ + return False + + +class OSBYTEhost(OSBYTE): + + def __init__(self, fs): + super(OSBYTEhost, self).__init__() + self.fs = fs + + self.dispatch[0x7F] = self.osbyte_eof + + def osbyte_eof(self, a, x, y, regs, memory): + fh = x + if self.fs.eof(fh): + regs.x = 0xFF + else: + regs.x = 0 + return True + + def host_fs_interfaces(basedir): """ Construct a list of OS interfaces for filesystems, using a host base directory. @@ -326,4 +468,6 @@ def host_fs_interfaces(basedir): lambda: OSBGEThost(fs), lambda: OSBPUThost(fs), lambda: OSARGShost(fs), + lambda: OSFSChost(fs), + lambda: OSBYTEhost(fs), ] From ce3919f2d361207465b5c5066b450f4b46695c3d Mon Sep 17 00:00:00 2001 From: Charles Ferguson <gerph@gerph.org> Date: Wed, 20 Dec 2023 00:44:51 +0000 Subject: [PATCH 44/65] Fix for OSARGS not triggering. Two hex digits in the code address for OSARGS had been transposed, meaning it was never called. And the EXT handler hadn't assigned the right variable. --- pybeeb/Host/base.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pybeeb/Host/base.py b/pybeeb/Host/base.py index db1a9bc..caa3c3b 100644 --- a/pybeeb/Host/base.py +++ b/pybeeb/Host/base.py @@ -490,7 +490,7 @@ def load(self, filename, load_address, regs, memory): class OSARGS(OSInterface): - code = 0xF1E8 + code = 0xF18E vector = 0x0214 def call(self, regs, memory): @@ -522,6 +522,7 @@ def osargs(self, op, fh, address, regs, memory): 255: Flush file to storage """ handled = False + #print("OSArgs: fh=%i, addr=%x" % (fh, address)) if fh == 0: # Filehandle = 0 if op == 0x00: @@ -557,7 +558,7 @@ def osargs(self, op, fh, address, regs, memory): elif op == 0x02: # Read EXT# - handled = self.read_ext(fh, regs, memory) + result = self.read_ext(fh, regs, memory) handled = result is not None if handled: memory.writeLongWord(address, result) From 51d96aba3d1e173fabdf3ff442c085f138d577f4 Mon Sep 17 00:00:00 2001 From: Charles Ferguson <gerph@gerph.org> Date: Wed, 20 Dec 2023 02:18:45 +0000 Subject: [PATCH 45/65] Update OSRDCH to allow buffer and *exec to be used. Buffering and *Exec are handled as part of OSRDCH, but we need to process the routing a little later, after all the code which retrieves from the file, and checks the buffer. That way, if there is buffered data, we'll use it. --- pybeeb/Host/base.py | 40 ++++++++++++++++++++++++++++++++++++++++ pybeeb/Host/hosttty.py | 4 ++-- 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/pybeeb/Host/base.py b/pybeeb/Host/base.py index caa3c3b..491e104 100644 --- a/pybeeb/Host/base.py +++ b/pybeeb/Host/base.py @@ -174,6 +174,9 @@ def writec(self, ch): class OSRDCH(OSInterface): + """ + OSRDCH entry at the top of the routine. + """ code = 0xDEC5 vector = 0x0210 @@ -200,6 +203,43 @@ def readc(self): return None +class OSRDCHpostbuffer(OSInterface): + """ + OSRDCH, but only after the buffer has been read. + + Handling this entry after the buffer has been read allows *EXEC and insertions through *Key and *FX138. + + => C = 0 if character already returned from buffer. + C = 1 if no character was read, in A + """ + code = 0xDEF0 + vector = None + + def call(self, regs, memory): + if not regs.carry: + # A character was already read + return False + + ch = self.readc() + if ch is None: + return False + + ch = ord(ch) + if ch == 27: + # Bit of a hack as we don't have interrupts + # Set the escape flag + memory.writeByte(0xFF, 0x80) + + regs.carry = False + regs.a = ch + + # The state we've just updated with will cause us to return the character + return False + + def readc(self): + return None + + class OSCLI(OSInterface): code = 0xDF89 vector = 0x0208 diff --git a/pybeeb/Host/hosttty.py b/pybeeb/Host/hosttty.py index f8cde8e..6aa07b0 100644 --- a/pybeeb/Host/hosttty.py +++ b/pybeeb/Host/hosttty.py @@ -4,7 +4,7 @@ import sys -from .base import OSInterface, OSWRCH, OSRDCH, OSWORD, OSBYTE, InputEOFError +from .base import OSInterface, OSWRCH, OSRDCHpostbuffer, OSWORD, OSBYTE, InputEOFError from .console import Console @@ -20,7 +20,7 @@ def writec(self, ch): return True -class OSRDCHtty(OSRDCH): +class OSRDCHtty(OSRDCHpostbuffer): def __init__(self): super(OSRDCHtty, self).__init__() From bfbe5a7808c8102dfdc3e506f00f5b635b778e7a Mon Sep 17 00:00:00 2001 From: Charles Ferguson <gerph@gerph.org> Date: Fri, 22 Dec 2023 23:53:26 +0000 Subject: [PATCH 46/65] Rename PyBeebicorn to Emulation; replace 'regs, memory' with 'pb'. The PyBeebicorn interface is now a main interface, with the name Emulation, instead of PyBeebicorn. This allows it to be passed around more freely. As such, instead of referring throug the regs and memory objects which are passed in, we now pass through the emulator obejct `pb`. --- PyBeebU.py | 15 +- pybeeb/{PyBeebicorn.py => Emulation.py} | 62 ++- pybeeb/Host/base.py | 560 +++++++++++------------- pybeeb/Host/hostfs.py | 160 +++---- pybeeb/Host/hosttty.py | 36 +- 5 files changed, 398 insertions(+), 435 deletions(-) rename pybeeb/{PyBeebicorn.py => Emulation.py} (89%) diff --git a/PyBeebU.py b/PyBeebU.py index ed7d0dd..5454994 100755 --- a/PyBeebU.py +++ b/PyBeebU.py @@ -8,7 +8,7 @@ import sys -from pybeeb.PyBeebicorn import Pb, PbError, PbConstants +from pybeeb.Emulation import Pb, PbError, PbConstants from pybeeb.Host import (BBCError, InputEOFError, OSInterface, OSCLI, OSBYTE, OSFILE, OSFIND, OSARGS, OSBPUT, OSBGET, OSGBPB, OSFSC) from pybeeb.Host.hosttty import OSWRCHtty, OSRDCHtty, OSWORDtty, OSBYTEtty @@ -85,13 +85,6 @@ def mem_hook(pb, access, address, size, value, user_data): OSBYTEversion, OSWORDtty, OSBYTEtty, - #OSFILE, - #OSFIND, - #OSARGS, - #OSBPUT, - #OSBGET, - #OSGBPB, - #OSFSC ] + host_fs_interfaces('.') try: syscalls = {} @@ -103,14 +96,14 @@ def mem_hook(pb, access, address, size, value, user_data): def hook(pb, address, size, user_data, interface=interface): try: #print("Call interface %r" % (interface,)) - handled = interface.call(pb.reg, pb.memory) + handled = interface.call(pb) #print(" handled = %r" % (handled,)) if handled: - pb.reg.pc = pb.dispatch.pullWord() + 1 + pb.regs.pc = pb.dispatch.pullWord() + 1 except BBCError as exc: pb.memory.writeBytes(0x100, bytearray([0, exc.errnum])) pb.memory.writeBytes(0x100 + 2, bytearray(exc.errmess.encode('latin-1'))) - pb.reg.pc = 0x100 + pb.regs.pc = 0x100 syscalls[interface.code] = hook diff --git a/pybeeb/PyBeebicorn.py b/pybeeb/Emulation.py similarity index 89% rename from pybeeb/PyBeebicorn.py rename to pybeeb/Emulation.py index b0db871..56ce00a 100644 --- a/pybeeb/PyBeebicorn.py +++ b/pybeeb/Emulation.py @@ -228,9 +228,9 @@ def execute(self, pc, length, opcode, instruction, writeback): for hook in self.hook_exec: if pc in hook: hook.call(pc, length) - if pc != self.pb.reg.pc: + if pc != self.pb.regs.pc: # They changed the execution location, so we're not running this instruction any more. - return self.pb.reg.pc + return self.pb.regs.pc if self.pb.executing: return super(PbDispatcher, self).execute(pc, length, opcode, instruction, writeback) @@ -359,24 +359,44 @@ def writeBytes(self, address, value, skip_hook=False): class Pb(object): """ - PyBeepicorn main object - similar to the Uc() objects in Unicorn. + PyBeep class - similar to the Uc() objects in Unicorn. + + There are properties and methods that can be used to access the emulator: + + * `pb.regs` - An object to access registers by name in lower case. + Flags are given their full name. + * `pb.memory` - An object to access memory. + Methods: + `readByte(address, value)` + `writeByte(address)` + `readBytes(address, size)` + `writeBytes(address, data)` + `readLongWord(address)` + `writeLongWord(address, value)` + `readString(address)` + * `pb.reg_read` - Read a register using the constants from PbConstants + (Unicorn-like interface) + * `pb.mem_read` - Read memory (Unicorn-like interface) + * `pb.mem_write` - Write memory (Unicorn-like interface) + * `pb.hook_add` - Add a hook to those that we will dispatch (code or memory access hooks) + * `pb.hook_del` - Remove a registered hook. """ insts_filename = os.path.join(os.path.dirname(__file__), 'insts.csv') def __init__(self): # We only support 6502, so there is no architecture or mode flag. self.memory = PbMemory(self) - self.reg = Registers.RegisterBank() - addrDispatch = AddressDispatcher.AddressDispatcher(self.memory, self.reg) + self.regs = Registers.RegisterBank() + addrDispatch = AddressDispatcher.AddressDispatcher(self.memory, self.regs) - execDispatch = ExecutionUnit.ExecutionDispatcher(self.memory,self.reg) - writebackDispatch = Writeback.Dispatcher(self.memory,self.reg) + execDispatch = ExecutionUnit.ExecutionDispatcher(self.memory, self.regs) + writebackDispatch = Writeback.Dispatcher(self.memory, self.regs) decoder = Decoder.Decoder(self.insts_filename) self.dispatch = PbDispatcher(self, decoder, addrDispatch, execDispatch, writebackDispatch, - self.memory, self.reg) + self.memory, self.regs) self.bbc = BBCMicro.System.Beeb(self.dispatch) self.dis = Disassemble6502Pb(self) @@ -385,34 +405,34 @@ def __init__(self): def write_pc(v): #print("Set PC to &%04x" % (v,)) - self.reg.pc = v & 0xFFFF + self.regs.pc = v & 0xFFFF def write_sp(v): - self.reg.sp = v & 0xFF + self.regs.sp = v & 0xFF def write_a(v): - self.reg.a = v & 0xFF + self.regs.a = v & 0xFF def write_x(v): - self.reg.x = v & 0xFF + self.regs.x = v & 0xFF def write_y(v): - self.reg.y = v & 0xFF + self.regs.y = v & 0xFF def read_pc(): - return self.reg.pc & 0xFFFF + return self.regs.pc & 0xFFFF def read_sp(): - return self.reg.sp & 0xFF + return self.regs.sp & 0xFF def read_a(): - return self.reg.a & 0xFF + return self.regs.a & 0xFF def read_x(): - return self.reg.x & 0xFF + return self.regs.x & 0xFF def read_y(): - return self.reg.y & 0xFF + return self.regs.y & 0xFF self.reg_dispatch = { PbConstants.PB_6502_REG_PC: (read_pc, write_pc), @@ -420,7 +440,7 @@ def read_y(): PbConstants.PB_6502_REG_A: (read_a, write_a), PbConstants.PB_6502_REG_X: (read_x, write_x), PbConstants.PB_6502_REG_Y: (read_y, write_y), - PbConstants.PB_6502_REG_PS: (lambda: self.reg.ps(), lambda v: self.reg.setPS(v)), + PbConstants.PB_6502_REG_PS: (lambda: self.regs.ps(), lambda v: self.regs.setPS(v)), } # emulate from @begin, and stop when reaching address @until @@ -428,8 +448,8 @@ def emu_start(self, begin, until, count=0): insts = 0 self.executing = True try: - while self.executing and self.reg.pc != until: - #print "%s: PC: %s" % (insts, hex(self.reg.pc)) + while self.executing and self.regs.pc != until: + #print "%s: PC: %s" % (insts, hex(self.regs.pc)) self.bbc.tick() insts += 1 diff --git a/pybeeb/Host/base.py b/pybeeb/Host/base.py index 491e104..88bad17 100644 --- a/pybeeb/Host/base.py +++ b/pybeeb/Host/base.py @@ -105,7 +105,7 @@ def __init__(self): # The dispatcher used will be called with the parameters # returned by the `dispatch_parameters` method. By default these # are: - # (A, X, Y, regs, memory) + # (A, X, Y, pb) self.dispatch = {} self.dispatch_default = None @@ -121,18 +121,17 @@ def stop(self): """ pass - def dispatch_parameters(self, regs, memory): + def dispatch_parameters(self, pb): """ Prepare a set of parameters to pass to the dispatcher. - @param regs: Registers object, containing a, x, y, pc, and sp properties + the flags - @param memory: Memory object, containing the (read|write)(Byte|Bytes|Word|SignedByte) methods + @param pb: Emulator object, containing `regs` and `memory` @return: list of parameters to pass to the dispatcher """ - return [regs.a, regs.x, regs.y, regs, memory] + return [pb.regs.a, pb.regs.x, pb.regs.y, pb] - def call(self, regs, memory): + def call(self, pb): """ Call the interface with a given set of parameters. @@ -140,21 +139,20 @@ def call(self, regs, memory): May raise exception BBCError to indicate that an error should be reported. - @param regs: Registers object, containing a, x, y, pc, and sp properties + the flags - @param memory: Memory object, containing the (read|write)(Byte|Bytes|Word|SignedByte) methods + @param pb: Emulator object, containing `regs` and `memory` @return: True if the call has been handled (return from interface), False if call should continue at the code execution point """ - dispatcher = self.dispatch.get((regs.a, regs.x, regs.y), None) + dispatcher = self.dispatch.get((pb.regs.a, pb.regs.x, pb.regs.y), None) if dispatcher is None: - dispatcher = self.dispatch.get((regs.a, regs.x), None) + dispatcher = self.dispatch.get((pb.regs.a, pb.regs.x), None) if dispatcher is None: - dispatcher = self.dispatch.get(regs.a, None) + dispatcher = self.dispatch.get(pb.regs.a, None) if dispatcher is None: dispatcher = self.dispatch_default if dispatcher: - params = self.dispatch_parameters(regs, memory) + params = self.dispatch_parameters(pb) return dispatcher(*params) return False @@ -163,8 +161,8 @@ class OSWRCH(OSInterface): code = 0xE0A4 vector = 0x020E - def call(self, regs, memory): - return self.writec(regs.a) + def call(self, pb): + return self.writec(pb.regs.a) def writec(self, ch): """ @@ -180,21 +178,21 @@ class OSRDCH(OSInterface): code = 0xDEC5 vector = 0x0210 - def call(self, regs, memory): + def call(self, pb): ch = self.readc() if ch is None: return False ch = ord(ch) if ch == 27: - regs.carry = True + pb.regs.carry = True # Bit of a hack as we don't have interrupts # Set the escape flag - memory.writeByte(0xFF, 0x80) + pb.memory.writeByte(0xFF, 0x80) else: - regs.carry = False - regs.a = ch + pb.regs.carry = False + pb.regs.a = ch # Return immediately with an RTS return True @@ -215,8 +213,8 @@ class OSRDCHpostbuffer(OSInterface): code = 0xDEF0 vector = None - def call(self, regs, memory): - if not regs.carry: + def call(self, pb): + if not pb.regs.carry: # A character was already read return False @@ -228,10 +226,10 @@ def call(self, regs, memory): if ch == 27: # Bit of a hack as we don't have interrupts # Set the escape flag - memory.writeByte(0xFF, 0x80) + pb.memory.writeByte(0xFF, 0x80) - regs.carry = False - regs.a = ch + pb.regs.carry = False + pb.regs.a = ch # The state we've just updated with will cause us to return the character return False @@ -244,9 +242,9 @@ class OSCLI(OSInterface): code = 0xDF89 vector = 0x0208 - def call(self, regs, memory): - xy = regs.x | (regs.y << 8) - cli = memory.readString(xy) + def call(self, pb): + xy = pb.regs.x | (pb.regs.y << 8) + cli = pb.memory.readString(xy) while cli[0:1] == b'*': cli = cli[1:] if b' ' in cli: @@ -269,7 +267,7 @@ def __init__(self): super(OSBYTE, self).__init__() self.dispatch_default = self.osbyte - def osbyte(self, a, x, y, regs, memory): + def osbyte(self, a, x, y, pb): return False @@ -281,17 +279,17 @@ def __init__(self): super(OSWORD, self).__init__() # The dispatcher used will be called with the parameters - # (a, address, regs, memory) + # (a, address, pb) self.dispatch_default = self.osword - def dispatch_parameters(self, regs, memory): + def dispatch_parameters(self, pb): """ Decode the paramters for the address. """ - address = regs.x | (regs.y << 8) - return [regs.a, address, regs, memory] + address = pb.regs.x | (pb.regs.y << 8) + return [pb.regs.a, address, pb] - def osword(self, a, address, regs, memory): + def osword(self, a, address, pb): return False @@ -303,16 +301,16 @@ def __init__(self): super(OSFILE, self).__init__() # The default dispatcher is called with: - # (op, filename, address, regs, memory) + # (op, filename, address, pb) self.dispatch_default = self.osfile - def dispatch_parameters(self, regs, memory): - address = regs.x | (regs.y << 8) - filename_ptr = memory.readWord(address) - filename = memory.readString(filename_ptr) - return [regs.a, filename, address, regs, memory] + def dispatch_parameters(self, pb): + address = pb.regs.x | (pb.regs.y << 8) + filename_ptr = pb.memory.readWord(address) + filename = pb.memory.readString(filename_ptr) + return [pb.regs.a, filename, address, pb] - def osfile(self, op, filename, address, regs, memory): + def osfile(self, op, filename, address, pb): """ Handle an OSFILE call. @@ -356,8 +354,7 @@ def osfile(self, op, filename, address, regs, memory): @param op: operation code from the A register @param filename: The filename to work with @param address: The address of the block for file operations - @param regs: Registers - @param memory: Memory access + @param pb: Emulator object, containing `regs` and `memory` @return: True if handled False if not handled @@ -366,73 +363,73 @@ def osfile(self, op, filename, address, regs, memory): if op == 0: # Save - src_address = memory.readLongWord(address + 10) - src_length = memory.readLongWord(address + 14) - src_address - info_load = memory.readLongWord(address + 2) - info_exec = memory.readLongWord(address + 6) - handled = self.save(filename, src_address, src_length, info_load, info_exec, regs, memory) + src_address = pb.memory.readLongWord(address + 10) + src_length = pb.memory.readLongWord(address + 14) - src_address + info_load = pb.memory.readLongWord(address + 2) + info_exec = pb.memory.readLongWord(address + 6) + handled = self.save(filename, src_address, src_length, info_load, info_exec, pb) elif op == 1: # Write load+exec+attr - info_load = memory.readLongWord(address + 2) - info_exec = memory.readLongWord(address + 6) - info_attr = memory.readLongWord(address + 14) - handled = self.write_info(filename, info_load, info_exec, info_attr, regs, memory) + info_load = pb.memory.readLongWord(address + 2) + info_exec = pb.memory.readLongWord(address + 6) + info_attr = pb.memory.readLongWord(address + 14) + handled = self.write_info(filename, info_load, info_exec, info_attr, pb) elif op == 2: # Write load - info_load = memory.readLongWord(address + 2) - handled = self.write_load(filename, info_load, regs, memory) + info_load = pb.memory.readLongWord(address + 2) + handled = self.write_load(filename, info_load, pb) elif op == 3: # Write exec - info_exec = memory.readLongWord(address + 6) - handled = self.write_exec(filename, info_exec, regs, memory) + info_exec = pb.memory.readLongWord(address + 6) + handled = self.write_exec(filename, info_exec, pb) elif op == 4: # Write attr - info_attr = memory.readLongWord(address + 14) - handled = self.write_attr(filename, info_attr, regs, memory) + info_attr = pb.memory.readLongWord(address + 14) + handled = self.write_attr(filename, info_attr, pb) elif op == 5: # Read load+exec+attr - result = self.read_info(filename, regs, memory) + result = self.read_info(filename, pb) if result: handled = True (info_type, info_load, info_exec, info_length, info_attr) = result - memory.writeLongWord(address + 2, info_load) - memory.writeLongWord(address + 6, info_exec) - memory.writeLongWord(address + 10, info_length) - memory.writeLongWord(address + 14, info_attr) - regs.a = info_type + pb.memory.writeLongWord(address + 2, info_load) + pb.memory.writeLongWord(address + 6, info_exec) + pb.memory.writeLongWord(address + 10, info_length) + pb.memory.writeLongWord(address + 14, info_attr) + pb.regs.a = info_type else: handled = False elif op == 6: # Delete - handled = self.delete(filename, regs, memory) + handled = self.delete(filename, pb) elif op == 255: # Load - if memory.readByte(address + 6) == 0: - load_address = memory.readLongWord(address + 2) + if pb.memory.readByte(address + 6) == 0: + load_address = pb.memory.readLongWord(address + 2) else: load_address = None - result = self.load(filename, load_address, regs, memory) + result = self.load(filename, load_address, pb) if result: handled = True (info_type, info_load, info_exec, info_length, info_attr) = result - memory.writeLongWord(address + 2, info_load) - memory.writeLongWord(address + 6, info_exec) - memory.writeLongWord(address + 10, info_length) - memory.writeLongWord(address + 14, info_attr) - regs.a = info_type + pb.memory.writeLongWord(address + 2, info_load) + pb.memory.writeLongWord(address + 6, info_exec) + pb.memory.writeLongWord(address + 10, info_length) + pb.memory.writeLongWord(address + 14, info_attr) + pb.regs.a = info_type else: handled = False return handled - def save(self, filename, src_address, src_length, info_load, info_exec, regs, memory): + def save(self, filename, src_address, src_length, info_load, info_exec, pb): """ @param filename: File to operate on @param src_address: Start address for save @@ -440,88 +437,80 @@ def save(self, filename, src_address, src_length, info_load, info_exec, regs, me @param info_load: Load address @param info_exec: Exec address @param info_attr: File attributes - @param regs: Registers object - @param memory: Memory object + @param pb: Emulator object, containing `regs` and `memory` @return: True if the call is handled, or False if it's not handled """ return False - def write_info(self, filename, info_load, info_exec, info_attr, regs, memory): + def write_info(self, filename, info_load, info_exec, info_attr, pb): """ @param filename: File to operate on @param info_load: Load address @param info_exec: Exec address @param info_attr: File attributes - @param regs: Registers object - @param memory: Memory object + @param pb: Emulator object, containing `regs` and `memory` @return: True if the call is handled, or False if it's not handled """ return False - def write_load(self, filename, info_load, regs, memory): + def write_load(self, filename, info_load, pb): """ @param filename: File to operate on @param info_load: Load address - @param regs: Registers object - @param memory: Memory object + @param pb: Emulator object, containing `regs` and `memory` @return: True if the call is handled, or False if it's not handled """ return False - def write_exec(self, filename, info_exec, regs, memory): + def write_exec(self, filename, info_exec, pb): """ @param filename: File to operate on @param info_exec: Exec address - @param regs: Registers object - @param memory: Memory object + @param pb: Emulator object, containing `regs` and `memory` @return: True if the call is handled, or False if it's not handled """ return False - def write_attr(self, filename, info_attr, regs, memory): + def write_attr(self, filename, info_attr, pb): """ @param filename: File to operate on @param info_attr: File attributes - @param regs: Registers object - @param memory: Memory object + @param pb: Emulator object, containing `regs` and `memory` @return: True if the call is handled, or False if it's not handled """ return False - def read_info(self, filename, regs, memory): + def read_info(self, filename, pb): """ @param filename: File to operate on @param info_load: Load address @param info_exec: Exec address @param info_attr: File attributes - @param regs: Registers object - @param memory: Memory object + @param pb: Emulator object, containing `regs` and `memory` @return: None if not handled, Tuple of (info_type, info_load, info_exec, info_length, info_attr) if handled """ return None - def delete(self, filename, regs, memory): + def delete(self, filename, pb): """ @param filename: File to operate on - @param regs: Registers object - @param memory: Memory object + @param pb: Emulator object, containing `regs` and `memory` @return: True if the call is handled, or False if it's not handled """ return False - def load(self, filename, load_address, regs, memory): + def load(self, filename, load_address, pb): """ @param filename: File to operate on - @param regs: Registers object - @param memory: Memory object + @param pb: Emulator object, containing `regs` and `memory` @return: None if not handled, Tuple of (info_type, info_load, info_exec, info_length, info_attr) if handled @@ -533,21 +522,21 @@ class OSARGS(OSInterface): code = 0xF18E vector = 0x0214 - def call(self, regs, memory): + def call(self, pb): # NOTE: We do not use the standard dispatcher mechanism here # because the primary discriminator is the Y register, # rather than the A register. - dispatcher = self.dispatch.get((regs.a, regs.y), None) + dispatcher = self.dispatch.get((pb.regs.a, pb.regs.y), None) if dispatcher is None: - dispatcher = self.dispatch.get(regs.a, None) + dispatcher = self.dispatch.get(pb.regs.a, None) if dispatcher is None: dispatcher = self.osargs - fh = regs.y - address = regs.x - return dispatcher(regs.a, fh, address, regs, memory) + fh = pb.regs.y + address = pb.regs.x + return dispatcher(pb.regs.a, fh, address, pb) - def osargs(self, op, fh, address, regs, memory): + def osargs(self, op, fh, address, pb): """ Handle OSARGS call for a given reason code and file handle. @@ -566,17 +555,17 @@ def osargs(self, op, fh, address, regs, memory): if fh == 0: # Filehandle = 0 if op == 0x00: - result = self.read_current_filesystem(regs, memory) + result = self.read_current_filesystem(pb) handled = result is not None if handled: - regs.a = result + pb.regs.a = result elif op == 0x01: # Read CLI args result = self.read_cli_args(regs, memory) handled = result is not None if handled: - memory.writeLongWord(address, result) + pb.memory.writeLongWord(address, result) elif op == 0xFF: # Flush all files @@ -586,107 +575,100 @@ def osargs(self, op, fh, address, regs, memory): # Filehandle supplied if op == 0x00: # Read PTR# - result = self.read_ptr(fh, regs, memory) + result = self.read_ptr(fh, pb) handled = result is not None if handled: - memory.writeLongWord(address, result) + pb.memory.writeLongWord(address, result) elif op == 0x01: # Write PTR# - ptr = memory.readLongWord(address) - handled = self.write_ptr(fh, ptr, regs, memory) + ptr = pb.memory.readLongWord(address) + handled = self.write_ptr(fh, ptr, pb) elif op == 0x02: # Read EXT# - result = self.read_ext(fh, regs, memory) + result = self.read_ext(fh, pb) handled = result is not None if handled: - memory.writeLongWord(address, result) + pb.memory.writeLongWord(address, result) elif op == 0xFF: # Flush file to storage - handled = self.flush_file(fh, regs, memory) + handled = self.flush_file(fh, pb) return False - def read_ptr(self, fh, regs, memory): + def read_ptr(self, fh, pb): """ Read PTR#. @param fh: File handle to read - @param regs: Registers object - @param memory: Memory object + @param pb: Emulator object, containing `regs` and `memory` @return: PTR for the file, or None if not handled """ return None - def read_ext(self, fh, regs, memory): + def read_ext(self, fh, pb): """ Read EXT#. @param fh: File handle to read - @param regs: Registers object - @param memory: Memory object + @param pb: Emulator object, containing `regs` and `memory` @return: EXT for the file, or None if not handled """ return None - def write_ptr(self, fh, ptr, regs, memory): + def write_ptr(self, fh, ptr, pb): """ Write PTR#. @param fh: File handle to read @param ptr: New PTR value - @param regs: Registers object - @param memory: Memory object + @param pb: Emulator object, containing `regs` and `memory` @return: True if handled, False if not handled """ return None - def flush_file(self, fh, regs, memory): + def flush_file(self, fh, pb): """ Flush file to storage. @param fh: File handle to read - @param regs: Registers object - @param memory: Memory object + @param pb: Emulator object, containing `regs` and `memory` @return: True if handled, False if not handled """ return False - def flush_all_files(self, regs, memory): + def flush_all_files(self, pb): """ Flush all files to storage @param fh: File handle to read - @param regs: Registers object - @param memory: Memory object + @param pb: Emulator object, containing `regs` and `memory` @return: True if handled, False if not handled """ return False - def read_current_filesystem(self, regs, memory): + def read_current_filesystem(self, pb): """ Read the current filesystem. - @param regs: Registers object - @param memory: Memory object + @param pb: Emulator object, containing `regs` and `memory` @return: Filesystem number, or None is not handled """ return None - def read_cli_args(self, regs, memory): + def read_cli_args(self, pb): """ Read the CLI arguments. - @param regs: Registers object - @param memory: Memory object + @param pb: Emulator object, containing `regs` and `memory` @return: Address of CLI arguments, or None is not handled """ @@ -697,24 +679,25 @@ class OSBGET(OSInterface): code = 0xF4C9 vector = 0x0216 - def call(self, regs, memory): - fh = regs.y - b = self.osbget(fh, regs, memory) + def call(self, pb): + fh = pb.regs.y + b = self.osbget(fh, pb) if b is None: return False if b == -1: - regs.carry = True + pb.regs.carry = True else: - regs.carry = False - regs.a = b + pb.regs.carry = False + pb.regs.a = b return True - def osbget(self, fh, regs, memory): + def osbget(self, fh, pb): """ Handle BGET, returning the byte read. @param fh: File handle to read + @param pb: Emulator object, containing `regs` and `memory` @return: byte read, -1 if at file end, or None if not handled """ @@ -725,18 +708,19 @@ class OSBPUT(OSInterface): code = 0xF529 vector = 0x0218 - def call(self, regs, memory): - fh = regs.y - b = regs.a - handled = self.osbput(b, fh, regs, memory) + def call(self, pb): + fh = pb.regs.y + b = pb.regs.a + handled = self.osbput(b, fh, pb) return handled - def osbput(self, b, fh, regs, memory): + def osbput(self, b, fh, pb): """ Handle BPUT, writing the supplied byte to a file.. @param fh: File handle to write to @param b: Byte to write + @param pb: Emulator object, containing `regs` and `memory` @return: True if handled, False if not handled. """ @@ -753,19 +737,19 @@ def __init__(self): self.dispatch[0x00] = self.call_close self.dispatch_default = self.call_open - def call_close(self, a, x, y, regs, memory): - return self.close(fh=y, regs=regs, memory=memory) + def call_close(self, a, x, y, pb): + return self.close(fh=y, pb=pb) - def call_open(self, a, x, y, regs, memory): + def call_open(self, a, x, y, pb): filename_ptr = x | (y << 8) - filename = memory.readString(filename_ptr) - fh = self.open(a, filename, regs, memory) + filename = pb.memory.readString(filename_ptr) + fh = self.open(a, filename, pb) if fh is None: return False - regs.a = fh + pb.regs.a = fh return True - def open(self, op, filename, regs, memory): + def open(self, op, filename, pb): """ Open a file for reading, writing or update. @@ -774,16 +758,18 @@ def open(self, op, filename, regs, memory): &80: output only &C0: input and output @param filename: file to open + @param pb: Emulator object, containing `regs` and `memory` @return: file handle, or 0 if failed to open, or None if not handled """ return None - def close(self, fh, regs, memory): + def close(self, fh, pb): """ Close a previously open file. @param fh: file handle to close, or 0 to close all files. + @param pb: Emulator object, containing `regs` and `memory` @return: True if handled; False if not handled. """ @@ -806,14 +792,14 @@ def __init__(self): self.dispatch[0x08] = self.call_get_filenames self.dispatch_default = self.osgbpb - def dispatch_parameters(self, regs, memory): + def dispatch_parameters(self, pb): """ Decode the parameters for the address. """ - address = regs.x | (regs.y << 8) - return [regs.a, address, regs, memory] + address = pb.regs.x | (pb.regs.y << 8) + return [pb.regs.a, address, pb] - def osgbpb(self, op, address, regs, memory): + def osgbpb(self, op, address, pb): """ The control block format is: @@ -844,212 +830,206 @@ def osgbpb(self, op, address, regs, memory): """ return False - def call_put_bytes(self, op, address, regs, memory): + def call_put_bytes(self, op, address, pb): """ Put bytes (at a given location). """ - fh = memory.readByte(address) - dataaddr = memory.readLongWord(address + 1) - datalen = memory.readLongWord(address + 5) + fh = pb.memory.readByte(address) + dataaddr = pb.memory.readLongWord(address + 1) + datalen = pb.memory.readLongWord(address + 5) if op == 1: - ptr = memory.readLongWord(address + 9) + ptr = pb.memory.readLongWord(address + 9) else: ptr = None - data = memory.readBytes(dataaddr, datalen) - result = self.put_bytes(fh, data, ptr, regs, memory) + data = pb.memory.readBytes(dataaddr, datalen) + result = self.put_bytes(fh, data, ptr, pb) if result: (transferred, newptr) = result if transferred != datalen: - regs.carry = True - memory.writeLongWord(address + 5, datalen - transferred) + pb.regs.carry = True + pb.memory.writeLongWord(address + 5, datalen - transferred) else: - regs.carry = False - memory.writeLongWord(address + 1, dataaddr + transferred) - memory.writeLongWord(address + 9, newptr) + pb.regs.carry = False + pb.memory.writeLongWord(address + 1, dataaddr + transferred) + pb.memory.writeLongWord(address + 9, newptr) handled = True else: handled = False return handled - def call_get_bytes(self, op, address, regs, memory): + def call_get_bytes(self, op, address, pb): """ Put bytes (at a given location). """ - fh = memory.readByte(address) - dataaddr = memory.readLongWord(address + 1) - datalen = memory.readLongWord(address + 5) + fh = pb.memory.readByte(address) + dataaddr = pb.memory.readLongWord(address + 1) + datalen = pb.memory.readLongWord(address + 5) if op == 1: - ptr = memory.readLongWord(address + 9) + ptr = pb.memory.readLongWord(address + 9) else: ptr = None - result = self.get_bytes(fh, datalen, ptr, regs, memory) + result = self.get_bytes(fh, datalen, ptr, pb) if result: (data, newptr) = result transferred = len(data) if transferred != datalen: - regs.carry = True - memory.writeLongWord(address + 5, datalen - transferred) + pb.regs.carry = True + pb.memory.writeLongWord(address + 5, datalen - transferred) else: - regs.carry = False - memory.writeLongWord(address + 1, dataaddr + transferred) - memory.writeLongWord(address + 9, newptr) - memory.writeBytes(dataaddr, data) + pb.regs.carry = False + pb.memory.writeLongWord(address + 1, dataaddr + transferred) + pb.memory.writeLongWord(address + 9, newptr) + pb.memory.writeBytes(dataaddr, data) handled = True else: handled = False return handled - def call_get_media_title(self, op, address, regs, memory): + def call_get_media_title(self, op, address, pb): """ Get media title and option as <len><title><option> """ - dataaddr = memory.readLongWord(address + 1) - datalen = memory.readLongWord(address + 5) - result = self.get_media_title(regs, memory) + dataaddr = pb.memory.readLongWord(address + 1) + datalen = pb.memory.readLongWord(address + 5) + result = self.get_media_title(pb) if result: (title, option) = result transferred = 1 + len(title) + 1 if transferred != datalen: - regs.carry = True - memory.writeLongWord(address + 5, datalen - transferred) + pb.regs.carry = True + pb.memory.writeLongWord(address + 5, datalen - transferred) else: - regs.carry = False + pb.regs.carry = False data = bytearray([len(title)]) + bytearray(title) + bytearray(option) - memory.writeLongWord(address + 1, dataaddr + transferred) - memory.writeLongWord(address + 9, transferred) - memory.writeBytes(dataaddr, data) + pb.memory.writeLongWord(address + 1, dataaddr + transferred) + pb.memory.writeLongWord(address + 9, transferred) + pb.memory.writeBytes(dataaddr, data) handled = True else: handled = False return handled - def call_get_csd_lib(self, op, address, regs, memory, csd): + def call_get_csd_lib(self, op, address, pb, csd): """ Get CSD/library and device as <len><device><len><csd> """ - dataaddr = memory.readLongWord(address + 1) - datalen = memory.readLongWord(address + 5) + dataaddr = pb.memory.readLongWord(address + 1) + datalen = pb.memory.readLongWord(address + 5) if csd: - result = self.get_csd(regs, memory) + result = self.get_csd(pb) else: - result = self.get_lib(regs, memory) + result = self.get_lib(pb) if result: (device, csd) = result transferred = 1 + len(device) + 1 + len(csd) if transferred != datalen: - regs.carry = True - memory.writeLongWord(address + 5, datalen - transferred) + pb.regs.carry = True + pb.memory.writeLongWord(address + 5, datalen - transferred) else: - regs.carry = False + pb.regs.carry = False data = bytearray([len(device)]) + bytearray(device) + bytearray([len(csd)]) + bytearray(csd) - memory.writeLongWord(address + 1, dataaddr + transferred) - memory.writeLongWord(address + 9, transferred) - memory.writeBytes(dataaddr, data) + pb.memory.writeLongWord(address + 1, dataaddr + transferred) + pb.memory.writeLongWord(address + 9, transferred) + pb.memory.writeBytes(dataaddr, data) handled = True else: handled = False return handled - def call_get_filenames(self, op, address, regs, memory, csd): + def call_get_filenames(self, op, address, pb, csd): """ Get filenames from the CSD, in form <length><filename>... """ - dataaddr = memory.readLongWord(address + 1) - nfiles = memory.readLongWord(address + 5) - offset = memory.readLongWord(address + 9) - filenames = self.get_csd_filenames(offset, nfiles, regs, memory) + dataaddr = pb.memory.readLongWord(address + 1) + nfiles = pb.memory.readLongWord(address + 5) + offset = pb.memory.readLongWord(address + 9) + filenames = self.get_csd_filenames(offset, nfiles, pb) if filenames is not None: transferred = len(filenames) if transferred != nfiles: - regs.carry = True - memory.writeLongWord(address + 5, nfiles - transferred) + pb.regs.carry = True + pb.memory.writeLongWord(address + 5, nfiles - transferred) else: - regs.carry = False + pb.regs.carry = False for filename in filenames: data = bytearray([len(filename)]) + bytearray(filename) - memory.writeBytes(dataaddr, data) + pb.memory.writeBytes(dataaddr, data) dataaddr += len(data) - memory.writeLongWord(address + 1, dataaddr) - memory.writeLongWord(address + 9, offset + transferred) + pb.memory.writeLongWord(address + 1, dataaddr) + pb.memory.writeLongWord(address + 9, offset + transferred) handled = True else: handled = False return handled - def put_bytes(self, fh, data, ptr, regs, memory): + def put_bytes(self, fh, data, ptr, pb): """ Put bytes to an open file handle. @param fh: File handle to read @param data: Data to write @param ptr: File pointer to write at, or None to write to current pointer - @param regs: Registers object - @param memory: Memory object + @param pb: Emulator object, containing `regs` and `memory` @return: None if not handled Tuple of (bytes transferred, new file pointer) """ return None - def get_bytes(self, fh, datalen, ptr, regs, memory): + def get_bytes(self, fh, datalen, ptr, pb): """ Get bytes from an open file handle. @param fh: File handle to read @param datalen: Length of data to read @param ptr: File pointer to read from, or None to read from current pointer - @param regs: Registers object - @param memory: Memory object + @param pb: Emulator object, containing `regs` and `memory` @return: None if not handled Tuple of (data read, new file pointer) """ return None - def get_media_title(self, regs, memory): + def get_media_title(self, pb): """ Get the media title and boot option - @param regs: Registers object - @param memory: Memory object + @param pb: Emulator object, containing `regs` and `memory` @return: None if not handled Tuple of (media title, boot option value) """ return None - def get_csd(self, regs, memory): + def get_csd(self, pb): """ Get the device name (eg "0" for disc 0) and CSD - @param regs: Registers object - @param memory: Memory object + @param pb: Emulator object, containing `regs` and `memory` @return: None if not handled Tuple of (device name, CSD) """ return None - def get_lib(self, regs, memory): + def get_lib(self, pb): """ Get the device name (eg "0" for disc 0) and library - @param regs: Registers object - @param memory: Memory object + @param pb: Emulator object, containing `regs` and `memory` @return: None if not handled Tuple of (device name, library directory) """ return None - def get_csd_filenames(self, nfiles, offset, regs, memory): + def get_csd_filenames(self, nfiles, offset, pb): """ Get filenames from the CSD. @param nfiles: Maximum number of files to read @param offset: Offset in directory list to start from - @param regs: Registers object - @param memory: Memory object + @param pb: Emulator object, containing `regs` and `memory` @return: None if not handled List of filenames if handled @@ -1074,14 +1054,14 @@ def __init__(self): self.dispatch[0x08] = self.call_star_command self.dispatch_default = self.osfsc - def dispatch_parameters(self, regs, memory): + def dispatch_parameters(self, pb): """ Decode the parameters for the address. """ - address = regs.x | (regs.y << 8) - return [regs.a, address, regs, memory] + address = pb.regs.x | (pb.regs.y << 8) + return [pb.regs.a, address, pb] - def osfsc(self, op, address, regs, memory): + def osfsc(self, op, address, pb): """ Operation codes: @@ -1097,103 +1077,101 @@ def osfsc(self, op, address, regs, memory): """ return False - def call_opt(self, op, address, regs, memory): + def call_opt(self, op, address, pb): """ *OPT X, Y issued """ - handled = self.opt(regs.x, regs.y, regs, memory) + handled = self.opt(pb.regs.x, pb.regs.y, pb) return handled - def call_eof(self, op, address, regs, memory): + def call_eof(self, op, address, pb): """ EOF check on a file handle. """ - fh = regs.x - eof = self.eof(fh, regs, memory) + fh = pb.regs.x + eof = self.eof(fh, pb) if eof is None: return False - regs.x = 0xFF if eof else 0x00 + pb.regs.x = 0xFF if eof else 0x00 return True - def call_slash(self, op, address, regs, memory): + def call_slash(self, op, address, pb): """ A /<command> has been issued """ - cli = memory.readString(address) + cli = pb.memory.readString(address) # FIXME: Should we split this up? - handled = self.slash(cli, regs, memory) + handled = self.slash(cli, pb) return handled - def call_ukcommand(self, op, address, regs, memory): + def call_ukcommand(self, op, address, pb): """ An unknown command has been issued """ - cli = memory.readString(address) + cli = pb.memory.readString(address) # FIXME: Should we split this up? - handled = self.ukcommand(cli, regs, memory) + handled = self.ukcommand(cli, pb) return handled - def call_run(self, op, address, regs, memory): + def call_run(self, op, address, pb): """ *Run has been issued """ - cli = memory.readString(address) + cli = pb.memory.readString(address) # FIXME: Should we split this up? - handled = self.run(cli, regs, memory) + handled = self.run(cli, pb) return handled - def call_cat(self, op, address, regs, memory): + def call_cat(self, op, address, pb): """ *Cat has been issued """ - cat = memory.readString(address) - handled = self.cat(cat, regs, memory) + cat = pb.memory.readString(address) + handled = self.cat(cat, pb) return handled - def call_fs_starting(self, op, address, regs, memory): + def call_fs_starting(self, op, address, pb): """ A new FS is starting up """ - handled = self.fs_starting(regs, memory) + handled = self.fs_starting(pb) return handled - def call_get_handle_range(self, op, address, regs, memory): + def call_get_handle_range(self, op, address, pb): """ Read the range of file handles supported. """ - result = self.get_handle_range(regs, memory) + result = self.get_handle_range(pb) if result is None: return False - (regs.x, regs.y) = result + (pb.regs.x, pb.regs.y) = result return True - def call_star_command(self, op, address, regs, memory): + def call_star_command(self, op, address, pb): """ New *command issued (for handling *Enable) """ - handled = self.star_command(regs, memory) + handled = self.star_command(pb) return handled - def opt(self, x, y, regs, memory): + def opt(self, x, y, pb): """ *OPT X, Y issued - @param x, y: Parameters to *Opt - @param regs: Registers object - @param memory: Memory object + @param x, y: Parameters to *Opt + @param pb: Emulator object, containing `regs` and `memory` @return: True if handled, False if not handled """ return False - def eof(self, fh, regs, memory): + def eof(self, fh, pb): """ EOF#fh check - @param fh: - @param regs: Registers object - @param memory: Memory object + @param fh: File handle to check + @param pb: Emulator object, containing `regs` and `memory` @return: True if EOF, False if not EOF, @@ -1201,87 +1179,79 @@ def eof(self, fh, regs, memory): """ return False - def slash(self, cli, regs, memory): + def slash(self, cli, pb): """ */<command> issued. - @param cli: CLI to execute - @param regs: Registers object - @param memory: Memory object + @param cli: CLI to execute + @param pb: Emulator object, containing `regs` and `memory` @return: True if handled, False if not handled """ return False - def ukcommand(self, cli, regs, memory): + def ukcommand(self, cli, pb): """ Unknown command issued - @param cli: Command issued - @param regs: Registers object - @param memory: Memory object + @param cli: Command issued + @param pb: Emulator object, containing `regs` and `memory` @return: True if handled, False if not handled """ return False - def run(self, run, regs, memory): + def run(self, run, pb): """ *Run issued. - @param run: Command to run - @param regs: Registers object - @param memory: Memory object + @param run: Command to run + @param pb: Emulator object, containing `regs` and `memory` @return: True if handled, False if not handled """ return False - def cat(self, dir, regs, memory): + def cat(self, dir, pb): """ *Cat issued - @param dir: Directory name - @param regs: Registers object - @param memory: Memory object + @param dir: Directory name + @param pb: Emulator object, containing `regs` and `memory` @return: True if handled, False if not handled """ return False - def fs_starting(self, regs, memory): + def fs_starting(self, pb): """ New FS is starting. - @param regs: Registers object - @param memory: Memory object + @param pb: Emulator object, containing `regs` and `memory` @return: True if handled, False if not handled """ return False - def get_handle_range(self, regs, memory): + def get_handle_range(self, pb): """ - @param regs: Registers object - @param memory: Memory object + @param pb: Emulator object, containing `regs` and `memory` @return: None if not handled Tuple of (low handle, high handle) if handled """ return False - def star_command(self, regs, memory): + def star_command(self, pb): """ - @param regs: Registers object - @param memory: Memory object + @param pb: Emulator object, containing `regs` and `memory` @return: True if handled, False if not handled """ return False - diff --git a/pybeeb/Host/hostfs.py b/pybeeb/Host/hostfs.py index 4842060..fc675e0 100644 --- a/pybeeb/Host/hostfs.py +++ b/pybeeb/Host/hostfs.py @@ -12,7 +12,7 @@ def __init__(self, fs): super(OSFILEhost, self).__init__() self.fs = fs - def save(self, filename, src_address, src_length, info_load, info_exec, regs, memory): + def save(self, filename, src_address, src_length, info_load, info_exec, pb): """ @param filename: File to operate on @param src_address: Start address for save @@ -20,37 +20,34 @@ def save(self, filename, src_address, src_length, info_load, info_exec, regs, me @param info_load: Load address @param info_exec: Exec address @param info_attr: File attributes - @param regs: Registers object - @param memory: Memory object + @param pb: Emulator object, containing `regs` and `memory` @return: True if the call is handled, or False if it's not handled """ self.fs.ensure_exists(filename, info_load, info_exec) handle = self.fs.open(filename, open_out) - data = memory.readBytes(src_address & 0xFFFF, src_length) + data = pb.memory.readBytes(src_address & 0xFFFF, src_length) self.fs.write(handle, data) return True - def write_info(self, filename, info_load, info_exec, info_attr, regs, memory): + def write_info(self, filename, info_load, info_exec, info_attr, pb): """ @param filename: File to operate on @param info_load: Load address @param info_exec: Exec address @param info_attr: File attributes - @param regs: Registers object - @param memory: Memory object + @param pb: Emulator object, containing `regs` and `memory` @return: True if the call is handled, or False if it's not handled """ self.fs.set_fileinfo(filename, info_load, info_exec, info_attr) return True - def write_load(self, filename, info_load, regs, memory): + def write_load(self, filename, info_load, pb): """ @param filename: File to operate on @param info_load: Load address - @param regs: Registers object - @param memory: Memory object + @param pb: Emulator object, containing `regs` and `memory` @return: True if the call is handled, or False if it's not handled """ @@ -58,12 +55,11 @@ def write_load(self, filename, info_load, regs, memory): self.fs.set_fileinfo(filename, info_load, info_exec, info_attr) return True - def write_exec(self, filename, info_exec, regs, memory): + def write_exec(self, filename, info_exec, pb): """ @param filename: File to operate on @param info_exec: Exec address - @param regs: Registers object - @param memory: Memory object + @param pb: Emulator object, containing `regs` and `memory` @return: True if the call is handled, or False if it's not handled """ @@ -71,12 +67,11 @@ def write_exec(self, filename, info_exec, regs, memory): self.fs.set_fileinfo(filename, info_load, info_exec, info_attr) return True - def write_attr(self, filename, info_attr, regs, memory): + def write_attr(self, filename, info_attr, pb): """ @param filename: File to operate on @param info_attr: File attributes - @param regs: Registers object - @param memory: Memory object + @param pb: Emulator object, containing `regs` and `memory` @return: True if the call is handled, or False if it's not handled """ @@ -84,14 +79,13 @@ def write_attr(self, filename, info_attr, regs, memory): self.fs.set_fileinfo(filename, info_load, info_exec, info_attr) return True - def read_info(self, filename, regs, memory): + def read_info(self, filename, pb): """ @param filename: File to operate on @param info_load: Load address @param info_exec: Exec address @param info_attr: File attributes - @param regs: Registers object - @param memory: Memory object + @param pb: Emulator object, containing `regs` and `memory` @return: None if not handled, Tuple of (info_type, info_load, info_exec, info_length, info_attr) if handled @@ -99,22 +93,20 @@ def read_info(self, filename, regs, memory): (info_type, info_load, info_exec, info_length, info_attr) = self.fs.fileinfo(filename) return (info_type, info_load, info_exec, info_length, info_attr) - def delete(self, filename, regs, memory): + def delete(self, filename, pb): """ @param filename: File to operate on - @param regs: Registers object - @param memory: Memory object + @param pb: Emulator object, containing `regs` and `memory` @return: True if the call is handled, or False if it's not handled """ self.fs.delete(filename) return True - def load(self, filename, load_address, regs, memory): + def load(self, filename, load_address, pb): """ @param filename: File to operate on - @param regs: Registers object - @param memory: Memory object + @param pb: Emulator object, containing `regs` and `memory` @return: None if not handled, Tuple of (info_type, info_load, info_exec, info_length, info_attr) if handled @@ -135,7 +127,7 @@ def load(self, filename, load_address, regs, memory): handle = self.fs.open(filename, open_in) size = self.fs.ext_read(handle) data = self.fs.read(handle, size) - memory.writeBytes(load_address & 0xFFFF, data) + pb.memory.writeBytes(load_address & 0xFFFF, data) finally: if handle: self.fs.close(handle) @@ -149,7 +141,7 @@ def __init__(self, fs): super(OSFINDhost, self).__init__() self.fs = fs - def open(self, op, filename, regs, memory): + def open(self, op, filename, pb): """ Open a file for reading, writing or update. @@ -158,6 +150,7 @@ def open(self, op, filename, regs, memory): &80: output only &C0: input and output @param filename: file to open + @param pb: Emulator object, containing `regs` and `memory` @return: file handle, or 0 if failed to open, or None if not handled """ @@ -168,11 +161,12 @@ def open(self, op, filename, regs, memory): return handle - def close(self, fh, regs, memory): + def close(self, fh, pb): """ Close a previously open file. @param fh: file handle to close, or 0 to close all files. + @param pb: Emulator object, containing `regs` and `memory` @return: True if handled; False if not handled. """ @@ -186,11 +180,12 @@ def __init__(self, fs): super(OSBGEThost, self).__init__() self.fs = fs - def osbget(self, fh, regs, memory): + def osbget(self, fh, pb): """ Handle BGET, returning the byte read. @param fh: File handle to read + @param pb: Emulator object, containing `regs` and `memory` @return: byte read, -1 if at file end, or None if not handled """ @@ -206,12 +201,13 @@ def __init__(self, fs): super(OSBPUThost, self).__init__() self.fs = fs - def osbput(self, b, fh, regs, memory): + def osbput(self, b, fh, pb): """ Handle BPUT, writing the supplied byte to a file.. @param fh: File handle to write to @param b: Byte to write + @param pb: Emulator object, containing `regs` and `memory` @return: True if handled, False if not handled. """ @@ -227,88 +223,81 @@ def __init__(self, fs): super(OSARGShost, self).__init__() self.fs = fs - def read_ptr(self, fh, regs, memory): + def read_ptr(self, fh, pb): """ Read PTR#. @param fh: File handle to read - @param regs: Registers object - @param memory: Memory object + @param pb: Emulator object, containing `regs` and `memory` @return: PTR for the file, or None if not handled """ ptr = self.fs.ptr_read(fh) return ptr - def read_ext(self, fh, regs, memory): + def read_ext(self, fh, pb): """ Read EXT#. @param fh: File handle to read - @param regs: Registers object - @param memory: Memory object + @param pb: Emulator object, containing `regs` and `memory` @return: EXT for the file, or None if not handled """ ext = self.fs.ext_read(fh) return ext - def write_ptr(self, fh, ptr, regs, memory): + def write_ptr(self, fh, ptr, pb): """ Write PTR#. @param fh: File handle to read @param ptr: New PTR value - @param regs: Registers object - @param memory: Memory object + @param pb: Emulator object, containing `regs` and `memory` @return: True if handled, False if not handled """ self.fs.ptr_write(fh, ptr) return True - def flush_file(self, fh, regs, memory): + def flush_file(self, fh, pb): """ Flush file to storage. @param fh: File handle to read - @param regs: Registers object - @param memory: Memory object + @param pb: Emulator object, containing `regs` and `memory` @return: True if handled, False if not handled """ self.fs.flush(fh) return True - def flush_all_files(self, regs, memory): + def flush_all_files(self, pb): """ Flush all files to storage @param fh: File handle to read - @param regs: Registers object - @param memory: Memory object + @param pb: Emulator object, containing `regs` and `memory` @return: True if handled, False if not handled """ return False - def read_current_filesystem(self, regs, memory): + def read_current_filesystem(self, pb): """ Read the current filesystem. - @param regs: Registers object - @param memory: Memory object + @param pb: Emulator object, containing `regs` and `memory` @return: Filesystem number, or None is not handled """ return 4 # FS_DFS - def read_cli_args(self, regs, memory): + def read_cli_args(self, pb): """ Read the CLI arguments. - @param regs: Registers object - @param memory: Memory object + @param pb: Emulator object, containing `regs` and `memory` @return: Address of CLI arguments, or None is not handled """ @@ -321,33 +310,31 @@ def __init__(self, fs): super(OSFSChost, self).__init__() self.fs = fs - def dispatch_parameters(self, regs, memory): + def dispatch_parameters(self, pb): """ Decode the parameters for the address. """ - address = regs.x | (regs.y << 8) - return [regs.a, address, regs, memory] + address = pb.regs.x | (pb.regs.y << 8) + return [pb.regs.a, address, pb] - def opt(self, x, y, regs, memory): + def opt(self, x, y, pb): """ *OPT X, Y issued - @param x, y: Parameters to *Opt - @param regs: Registers object - @param memory: Memory object + @param x, y: Parameters to *Opt + @param pb: Emulator object, containing `regs` and `memory` @return: True if handled, False if not handled """ return False - def eof(self, fh, regs, memory): + def eof(self, fh, pb): """ EOF#fh check - @param fh: - @param regs: Registers object - @param memory: Memory object + @param fh: File handle + @param pb: Emulator object, containing `regs` and `memory` @return: True if EOF, False if not EOF, @@ -355,84 +342,77 @@ def eof(self, fh, regs, memory): """ return self.fs.eof(fh) - def slash(self, cli, regs, memory): + def slash(self, cli, pb): """ */<command> issued. - @param cli: CLI to execute - @param regs: Registers object - @param memory: Memory object + @param cli: CLI to execute + @param pb: Emulator object, containing `regs` and `memory` @return: True if handled, False if not handled """ return False - def ukcommand(self, cli, regs, memory): + def ukcommand(self, cli, pb): """ Unknown command issued - @param cli: Command issued - @param regs: Registers object - @param memory: Memory object + @param cli: Command issued + @param pb: Emulator object, containing `regs` and `memory` @return: True if handled, False if not handled """ return False - def run(self, run, regs, memory): + def run(self, run, pb): """ *Run issued. - @param run: Command to run - @param regs: Registers object - @param memory: Memory object + @param run: Command to run + @param pb: Emulator object, containing `regs` and `memory` @return: True if handled, False if not handled """ return False - def cat(self, dir, regs, memory): + def cat(self, dir, pb): """ *Cat issued - @param dir: Directory name - @param regs: Registers object - @param memory: Memory object + @param dir: Directory name + @param pb: Emulator object, containing `regs` and `memory` @return: True if handled, False if not handled """ return False - def fs_starting(self, regs, memory): + def fs_starting(self, pb): """ New FS is starting. - @param regs: Registers object - @param memory: Memory object + @param pb: Emulator object, containing `regs` and `memory` @return: True if handled, False if not handled """ return False - def get_handle_range(self, regs, memory): + def get_handle_range(self, pb): """ - @param regs: Registers object - @param memory: Memory object + @param pb: Emulator object, containing `regs` and `memory` @return: None if not handled Tuple of (low handle, high handle) if handled """ return self.fs.handle_range() - def star_command(self, regs, memory): + def star_command(self, pb): """ - @param regs: Registers object - @param memory: Memory object + @param pb: Emulator object, containing `regs` and `memory` @return: True if handled, False if not handled @@ -448,12 +428,12 @@ def __init__(self, fs): self.dispatch[0x7F] = self.osbyte_eof - def osbyte_eof(self, a, x, y, regs, memory): + def osbyte_eof(self, a, x, y, pb): fh = x if self.fs.eof(fh): - regs.x = 0xFF + pb.regs.x = 0xFF else: - regs.x = 0 + pb.regs.x = 0 return True diff --git a/pybeeb/Host/hosttty.py b/pybeeb/Host/hosttty.py index 6aa07b0..eba96cc 100644 --- a/pybeeb/Host/hosttty.py +++ b/pybeeb/Host/hosttty.py @@ -57,7 +57,7 @@ def start(self): def stop(self): self.console.terminal_reset() - def inkey(self, a, x, y, regs, memory): + def inkey(self, a, x, y, pb): if y == 0xFF and x == 0: # Read machine type return False @@ -74,16 +74,16 @@ def inkey(self, a, x, y, regs, memory): if ch is not None: # If a character is detected, X=ASCII value of key pressed, Y=0 and C=0. - regs.x = ord(ch) - regs.y = 0 - regs.carry = False + pb.regs.x = ord(ch) + pb.regs.y = 0 + pb.regs.carry = False else: # If a character is not detected within timeout then Y=&FF and C=1. - regs.y = 0xff - regs.carry = False + pb.regs.y = 0xff + pb.regs.carry = False if ch == b'\x1b': # If Escape is pressed then Y=&1B (27) and C=1. - regs.carry = True + pb.regs.carry = True return True @@ -99,10 +99,10 @@ def __init__(self): # The keys in the dictionary may the value of the A register. # If no matching key exists, the method `osword` will be used. # The dispatcher used will be called with the parameters - # `(a, address, regs, memory)`. + # `(a, address, pb)`. self.dispatch[0x00] = self.osword_readline - def osword_readline(self, a, address, regs, memory): + def osword_readline(self, a, address, pb): # The parameter block: # XY+ 0 Buffer address for input LSB # 1 MSB @@ -117,10 +117,10 @@ def osword_readline(self, a, address, regs, memory): # C=1 if an ESCAPE condition terminated input. # Y contains line length, including carriage return if # used. - input_memory = memory.readWord(address) - maxline = memory.readByte(address + 2) - lowest = memory.readByte(address + 3) - highest = memory.readByte(address + 4) + input_memory = pb.memory.readWord(address) + maxline = pb.memory.readByte(address + 2) + lowest = pb.memory.readByte(address + 3) + highest = pb.memory.readByte(address + 4) try: sys.stdout.flush() @@ -128,16 +128,16 @@ def osword_readline(self, a, address, regs, memory): result = result[:maxline - 1] result = result + '\r' # FIXME: Note that the lowest and highest are not honoured by this - regs.carry = False - regs.y = len(result) - memory.writeBytes(input_memory, bytearray(result.encode('latin-1'))) + pb.regs.carry = False + pb.regs.y = len(result) + pb.memory.writeBytes(input_memory, bytearray(result.encode('latin-1'))) except EOFError: raise InputEOFError("EOF received from terminal") except KeyboardInterrupt: - regs.carry = True - regs.y = 0 + pb.regs.carry = True + pb.regs.y = 0 return True From 9e57509b284392dbf6324143ee6a283c84b9788c Mon Sep 17 00:00:00 2001 From: Charles Ferguson <gerph@gerph.org> Date: Sat, 23 Dec 2023 10:47:39 +0000 Subject: [PATCH 47/65] Add MOS interfaces to call code; implement *CAT. We now have a MOS interface that allows us to call 6502 code which is necessary to write characters to the display. And we use this with the *CAT interface. We also have a CWD in the filesystem now. --- pybeeb/CPU/Registers.py | 43 +++++++++++++++ pybeeb/Emulation.py | 25 ++++++--- pybeeb/Host/base.py | 14 ++--- pybeeb/Host/fsbbc.py | 58 ++++++++++++++++---- pybeeb/Host/hostfs.py | 54 +++++++++++++++++-- pybeeb/MOS.py | 117 ++++++++++++++++++++++++++++++++++++++++ 6 files changed, 284 insertions(+), 27 deletions(-) create mode 100644 pybeeb/MOS.py diff --git a/pybeeb/CPU/Registers.py b/pybeeb/CPU/Registers.py index 1a3bdff..cca74c9 100644 --- a/pybeeb/CPU/Registers.py +++ b/pybeeb/CPU/Registers.py @@ -4,6 +4,9 @@ @author: chris.whitworth ''' +import sys + + class RegisterBank(object): def __init__(self): @@ -59,6 +62,46 @@ def reset(self): self.sp = 0xff self.setPS(0) + def copy(self): + """ + Create a copy of the current register bank. + """ + new = self.__class__() + new.pc = self.pc + new.sp = self.sp + new.a = self.a + new.x = self.x + new.y = self.y + new.nextPC = self.nextPC + + new.carry = self.carry + new.zero = self.zero + new.int = self.int + new.dec = self.dec + new.brk = self.brk + new.overflow = self.overflow + new.negative = self.negative + return new + + def restore(self, old): + """ + Restore the state to that of an old register bank. + """ + self.pc = old.pc + self.sp = old.sp + self.a = old.a + self.x = old.x + self.y = old.y + self.nextPC = old.nextPC + + self.carry = old.carry + self.zero = old.zero + self.int = old.int + self.dec = old.dec + self.brk = old.brk + self.overflow = old.overflow + self.negative = old.negative + def status(self): sys.stdout.write("%s%s.%s%s%s%s%s" % ( "N" if self.negative else "-", diff --git a/pybeeb/Emulation.py b/pybeeb/Emulation.py index 56ce00a..d39e1b8 100644 --- a/pybeeb/Emulation.py +++ b/pybeeb/Emulation.py @@ -7,13 +7,14 @@ import os.path -from .CPU import Memory as Memory -from .CPU import Registers as Registers -from .CPU import AddressDispatcher as AddressDispatcher -from .CPU import Writeback as Writeback -from .CPU import ExecutionUnit as ExecutionUnit -from .CPU import Dispatch as Dispatch +from .CPU import Memory +from .CPU import Registers +from .CPU import AddressDispatcher +from .CPU import Writeback +from .CPU import ExecutionUnit +from .CPU import Dispatch from .CPU import InstructionDecoder as Decoder +from .CPU.ExecutionUnit import ExecutionException, StackOverflowException, StackUnderflowException from . import BBCMicro from .BBCMicro import System as BBCMicroSystem @@ -180,10 +181,10 @@ def read_word(self, address): return self.pb.memory.readWord(address) def reg_x(self): - return self.pb.reg.x + return self.pb.regs.x def reg_y(self): - return self.pb.reg.y + return self.pb.regs.y class PbHook(object): @@ -380,6 +381,7 @@ class Pb(object): * `pb.mem_write` - Write memory (Unicorn-like interface) * `pb.hook_add` - Add a hook to those that we will dispatch (code or memory access hooks) * `pb.hook_del` - Remove a registered hook. + * `pb.mos` - Access to MOS interfaces programatically """ insts_filename = os.path.join(os.path.dirname(__file__), 'insts.csv') @@ -401,6 +403,11 @@ def __init__(self): self.bbc = BBCMicro.System.Beeb(self.dispatch) self.dis = Disassemble6502Pb(self) + # Layering violation here, as MOS relies on reading our constants. + # FIXME: Refactor this + from .MOS import MOS + self.mos = MOS(self) + self.executing = False def write_pc(v): @@ -447,6 +454,8 @@ def read_y(): def emu_start(self, begin, until, count=0): insts = 0 self.executing = True + if begin is not None: + self.regs.pc = begin try: while self.executing and self.regs.pc != until: #print "%s: PC: %s" % (insts, hex(self.regs.pc)) diff --git a/pybeeb/Host/base.py b/pybeeb/Host/base.py index 88bad17..b699d87 100644 --- a/pybeeb/Host/base.py +++ b/pybeeb/Host/base.py @@ -562,14 +562,14 @@ def osargs(self, op, fh, address, pb): elif op == 0x01: # Read CLI args - result = self.read_cli_args(regs, memory) + result = self.read_cli_args(pb) handled = result is not None if handled: pb.memory.writeLongWord(address, result) elif op == 0xFF: # Flush all files - handled = self.flush_all_files(regs, memory) + handled = self.flush_all_files(pb) else: # Filehandle supplied @@ -787,8 +787,8 @@ def __init__(self): self.dispatch[0x03] = self.call_get_bytes self.dispatch[0x04] = self.call_get_bytes self.dispatch[0x05] = self.call_get_media_title - self.dispatch[0x06] = lambda op, address, regs, memory: self.call_get_csd_lib(op, address, regs, memory, csd=True) - self.dispatch[0x07] = lambda op, address, regs, memory: self.call_get_csd_lib(op, address, regs, memory, csd=False) + self.dispatch[0x06] = lambda op, address, pb: self.call_get_csd_lib(op, address, pb, csd=True) + self.dispatch[0x07] = lambda op, address, pb: self.call_get_csd_lib(op, address, pb, csd=False) self.dispatch[0x08] = self.call_get_filenames self.dispatch_default = self.osgbpb @@ -1038,7 +1038,7 @@ def get_csd_filenames(self, nfiles, offset, pb): class OSFSC(OSInterface): - code = 0xFFB1 + code = 0xF1B1 vector = 0x021E def __init__(self): @@ -1126,8 +1126,8 @@ def call_cat(self, op, address, pb): """ *Cat has been issued """ - cat = pb.memory.readString(address) - handled = self.cat(cat, pb) + path = pb.memory.readString(address) + handled = self.cat(path, pb) return handled def call_fs_starting(self, op, address, pb): diff --git a/pybeeb/Host/fsbbc.py b/pybeeb/Host/fsbbc.py index f72b664..b763430 100644 --- a/pybeeb/Host/fsbbc.py +++ b/pybeeb/Host/fsbbc.py @@ -2,9 +2,9 @@ Interfaces to the host filesystem. """ +import errno import os import stat -import sys from .base import BBCError @@ -38,7 +38,6 @@ class DirectoryEntry(object): def __init__(self, fs, native_name, parent): self.fs = fs self.native_name = native_name or '' - self.name = native_name self.parent = parent self.loadaddr = self.default_loadaddr @@ -224,7 +223,12 @@ def __init__(self, fs, name, parent): @property def files(self): if not self._files: - filenames = os.listdir(self.fullpath_native) + try: + filenames = os.listdir(self.fullpath_native) + except OSError as exc: + if exc.errno == errno.ENOENT: + # FIXME: Find the error number + raise BBCFileNotFoundError(0, "File '%s' not found" % (self.name,)) files = {} #print("Files in %r (%r)" % (self.fullpath, self.fullpath_native)) @@ -334,6 +338,7 @@ def __init__(self, basedir="."): self.cached = {} self.filehandles = {} self._next_filehandle = self.filehandle_max + self._cwd = '$' try: self.native_uid = os.getuid() @@ -415,21 +420,48 @@ def generate_native_filename(self, name, loadaddr, execaddr, objtype): return new_name def split(self, path): - parts = ['$'] + parts = [] for part in path.split('.'): if part == '$': parts = ['$'] elif part == '^': - if len(parts) > 1: - parts = parts[:-1] + if len(parts) > 1 and part[-1] != '^': + if part[-1] != '$': + parts = parts[:-1] + else: + part.append('^') else: parts.append(part) return parts def canonicalise(self, path): - parts = self.split(path) + cwd_parts = self.split(self._cwd) + path_parts = self.split(path) + if not path_parts: + # This is the CWD + parts = cwd_parts + elif path_parts and path_parts[0] == '$': + # This is already rooted + parts = path_parts + else: + while path_parts and path_parts[0] == '^': + if cwd_parts: + cwd_parts = cwd_parts[:-1] + path_parts = path_parts[1:] + if cwd_parts: + parts = cwd_parts + path_parts + else: + parts = ['$'] return '.'.join(parts) + @property + def cwd(self): + return self._cwd + + @cwd.setter + def cwd(self, value): + self._cwd = self.canonicalise(value) + def dirname(self, path): parts = self.split(path) if parts: @@ -448,8 +480,14 @@ def splitname(self, path): leafname = parts[-1] return (dirname, leafname) - def dir(self, path): - path = self.canonicalise(path) + def dir(self, path=None): + """ + Get the directory object for a given directory. + """ + if not path: + path = self.cwd + else: + path = self.canonicalise(path) #print("dir(%s)" % (path,)) dir = self.cached.get(path.lower(), None) if dir is None: @@ -465,6 +503,7 @@ def dir(self, path): return dir def find(self, path): + path = self.canonicalise(path) (dirname, leafname) = self.splitname(path) dir = self.dir(dirname) dirent = dir[leafname] @@ -517,6 +556,7 @@ def ensure_exists(self, path, loadaddr, execaddr): """ Ensure a file exists, creating it if needed, renaming if not. """ + path = self.canonicalise(path) (dirname, leafname) = self.splitname(path) dir = self.dir(dirname) diff --git a/pybeeb/Host/hostfs.py b/pybeeb/Host/hostfs.py index fc675e0..ae6fa80 100644 --- a/pybeeb/Host/hostfs.py +++ b/pybeeb/Host/hostfs.py @@ -378,17 +378,65 @@ def run(self, run, pb): """ return False - def cat(self, dir, pb): + def cat(self, path, pb): """ *Cat issued - @param dir: Directory name + @param path: Directory name, or empty for CWD @param pb: Emulator object, containing `regs` and `memory` @return: True if handled, False if not handled """ - return False + dir = self.fs.dir(path) + files = dir.files + longest_name = max(len(dirent.name) for dirent in files.values()) + longest_name = max(10, longest_name) + + pb.mos.write("Dir. %s\n\n" % (dir.fullpath,)) + + ordered = sorted(files.items()) + width = 40 + # FIXME: Make the width configurable (or read from the mode vars?) + x = 0 + for key, dirent in ordered: + text = "%-*s " % (longest_name, dirent.name) + attr = [] + if dirent.objtype == 2: + attr.append('D') + + if dirent.attributes & 8: + attr.append('L') + if dirent.attributes & 4: + attr.append('E') + if dirent.attributes & 2: + attr.append('W') + if dirent.attributes & 1: + attr.append('R') + attr.append('/') + if dirent.attributes & 0x80: + attr.append('L') + if dirent.attributes & 0x40: + attr.append('E') + if dirent.attributes & 0x20: + attr.append('W') + if dirent.attributes & 0x10: + attr.append('R') + + text += "%-10s " % (''.join(attr),) + + x += len(text) + if x > width: + pb.mos.write(b'\n') + x = len(text) + + pb.mos.write(text) + + if x != 0: + pb.mos.write(b'\n') + + pb.mos.write("\n%s files\n" % (len(files),)) + return True def fs_starting(self, pb): """ diff --git a/pybeeb/MOS.py b/pybeeb/MOS.py new file mode 100644 index 0000000..4f9281a --- /dev/null +++ b/pybeeb/MOS.py @@ -0,0 +1,117 @@ +""" +Python interfaces to allow calling the MOS interfaces. +""" + +from .Emulation import PbConstants, StackOverflowException, StackUnderflowException + + +class ExecutionComplete(Exception): + pass + + +class MOS(object): + return_address = 0xFFFF + + def __init__(self, pb): + self.pb = pb + + def push_byte(self, value): + self.pb.memory.writeByte(self.pb.regs.sp + 0x100, value) + self.pb.regs.sp -= 1 + if self.pb.regs.sp < 0x00: + raise StackOverflowException() + + def pull_byte(self): + self.pb.regs.sp += 1 + if self.pb.regs.sp > 0xff: + raise StackUnderflowException() + + return self.pb.memory.readByte(self.pb.regs.sp + 0x100) + + def push_word(self, value): + self.push_byte(value >> 8) + self.push_byte(value & 0xff) + + def pull_word(self): + lw = self.pull_byte() + hw = self.pull_byte() << 8 + return lw + hw + + def push_pc(self): + self.push_word(self.pb.regs.pc) + + def pop_pc(self): + self.pb.regs.pc = self.pull_word() + rts = pop_pc + + def _execution_complete(self): + raise ExecutionComplete("Return from internal call (abnormal)") + + def call(self, address, a=None, x=None, y=None, preserve_state=True): + """ + Call a routine in the system (doesn't have to be a MOS routine). + + @param address: Address to call + @param a, x, y: Register values to use, or None to not set them + @param preserve_state: True to preserve all the calling registers + """ + old_regs = self.pb.regs.copy() + self.push_pc() + self.push_word(self.return_address - 1) + was_executing = self.pb.executing + + if a is not None: + self.pb.regs.a = a + if x is not None: + self.pb.regs.x = x + if y is not None: + self.pb.regs.y = y + + # Add a hook so that we can exit cleanly + self.pb.hook_add(PbConstants.PB_HOOK_CODE, + self._execution_complete, + begin=self.return_address, end=self.return_address + 1) + + try: + self.pb.emu_start(address, until=self.return_address) + except ExecutionComplete: + # The emulation ended with a return from the internal call that wasn't detected + # by emu_start. This means that we probably called to a routine that subsequently + # called emu_start and then exited via our hook. This probably means an unbalanced + # stack. For now we just let this be an exception. + raise + + self.pop_pc() + regs = self.pb.regs + if preserve_state: + regs = self.pb.regs.copy() + self.pb.regs.restore(old_regs) + + self.pb.executing = was_executing + return regs + + def oswrch(self, c): + self.call(0xFFEE, a=c, preserve_state=True) + + def osasci(self, c): + self.call(0xFFE3, a=c, preserve_state=True) + + def write(self, msg): + if isinstance(msg, bytes): + data = bytearray(msg) + elif isinstance(msg, str): + # Let's use latin-1 as our encoding for now. + data = msg.encode('latin-1') + data = bytearray(data) + for c in data: + self.osasci(c) + + def writeraw(self, msg): + if isinstance(msg, bytes): + data = bytearray(msg) + elif isinstance(msg, str): + # Let's use latin-1 as our encoding for now. + data = msg.encode('latin-1') + data = bytearray(data) + for c in data: + self.oswrch(c) From e343cf4e3465ea288ee09e3c5f76ae16ef72f640 Mon Sep 17 00:00:00 2001 From: Charles Ferguson <gerph@gerph.org> Date: Sat, 23 Dec 2023 11:47:20 +0000 Subject: [PATCH 48/65] Add support for *DIR. We now support *DIR properly, and we have a number of fixes for command line uses. --- PyBeeb.py | 6 ++++-- PyBeebU.py | 19 ++++++++++------- pybeeb/Host/base.py | 49 ++++++++++++++++++++++++++++++++++++------- pybeeb/Host/fsbbc.py | 17 +++++++++++++-- pybeeb/Host/hostfs.py | 16 +++++++++++++- 5 files changed, 87 insertions(+), 20 deletions(-) diff --git a/PyBeeb.py b/PyBeeb.py index 8e5fadf..4229629 100755 --- a/PyBeeb.py +++ b/PyBeeb.py @@ -55,6 +55,8 @@ def __init__(self, pcTrace = False, verbose = False): def go(self, syscalls): instr = 0 + # NOTE: We only support a single handler per address. + syscalls = dict(syscalls) while True: if self.pcTrace: @@ -76,7 +78,7 @@ def OS_RDCH(reg,mem): print "OS_RDCH" # Could inject keypresses here maybe? if __name__ == "__main__": OS_WRCH_LOC = 0xe0a4 OS_RDCH_LOC = 0xdec5 - syscalls = { OS_WRCH_LOC : OS_WRCH, - OS_RDCH_LOC : OS_RDCH } + syscalls = [ (OS_WRCH_LOC, OS_WRCH), + (OS_RDCH_LOC, OS_RDCH) ] bbc = BBC() bbc.go(syscalls) diff --git a/PyBeebU.py b/PyBeebU.py index 5454994..537b7b4 100755 --- a/PyBeebU.py +++ b/PyBeebU.py @@ -23,7 +23,7 @@ def go(self, syscalls): try: # Register the syscall execution entry points hooks = [] - for addr, func in syscalls.items(): + for addr, func in syscalls: hooks.append(self.pb.hook_add(PbConstants.PB_HOOK_CODE, func, begin=addr, end=addr + 1)) @@ -36,10 +36,13 @@ def go(self, syscalls): class OSCLIquit(OSCLI): - def command(self, command, args): - if command == b'QUIT': - sys.exit() - return False + def __init__(self, *args, **kwargs): + super(OSCLIquit, self).__init__(*args, **kwargs) + + self.commands_dispatch['QUIT'] = self.cmd_quit + + def cmd_quit(self, args, pb): + sys.exit() class OSBYTEversion(OSBYTE): @@ -49,7 +52,7 @@ def __init__(self): self.dispatch[(0x00, 0x00)] = self.osbyte_osversion_error - def osbyte_osversion_error(self, a, x, y, regs, memory): + def osbyte_osversion_error(self, a, x, y, pb): raise BBCError(247, "OS 1.20 (PyBeeb)") @@ -87,7 +90,7 @@ def mem_hook(pb, access, address, size, value, user_data): OSBYTEtty, ] + host_fs_interfaces('.') try: - syscalls = {} + syscalls = [] interfaces = [] for cls in interface_classes: interface = cls() @@ -105,7 +108,7 @@ def hook(pb, address, size, user_data, interface=interface): pb.memory.writeBytes(0x100 + 2, bytearray(exc.errmess.encode('latin-1'))) pb.regs.pc = 0x100 - syscalls[interface.code] = hook + syscalls.append((interface.code, hook)) bbc.go(syscalls) diff --git a/pybeeb/Host/base.py b/pybeeb/Host/base.py index b699d87..3078648 100644 --- a/pybeeb/Host/base.py +++ b/pybeeb/Host/base.py @@ -242,20 +242,55 @@ class OSCLI(OSInterface): code = 0xDF89 vector = 0x0208 + def __init__(self): + super(OSCLI, self).__init__() + + # The command dispatch table can be used to make it easier + # to handle individual commands. The key is an upper case + # command name, and the value is a method which should be + # called to handle it. The method will be called as: + # method(args, pb) + self.commands_dispatch = {} + def call(self, pb): xy = pb.regs.x | (pb.regs.y << 8) cli = pb.memory.readString(xy) - while cli[0:1] == b'*': + while cli[0:1] in (b'*', b' '): cli = cli[1:] - if b' ' in cli: - (command, args) = cli.split(b' ', 1) + + cmd = [] + args = '' + abbrev = False + for index, c in enumerate(cli): + if c == ' ': + args = cli[index + 1:] + break + if c == '.': + args = cli[index + 1:] + abbrev = True + break + cmd.append(c.upper()) + + dispatch = None + command = ''.join(cmd) + #print("CMD: %r (abbrev=%s), args: %r" % (command, abbrev, args)) + if abbrev: + if not command: + # Always give up on the `*.` command, so that it's + # passed on to the OS to be handled as *CAT through + # OSFSC. + return False + for key, func in self.commands_dispatch.items(): + if key.startswith(command): + dispatch = func else: - command = cli - args = b'' + dispatch = self.commands_dispatch.get(command, None) + if dispatch: + return dispatch(args, pb) - return self.command(command.upper(), args) + return self.command(command, args, pb) - def command(self, command, args): + def command(self, command, args, pb): return False diff --git a/pybeeb/Host/fsbbc.py b/pybeeb/Host/fsbbc.py index b763430..dc0994e 100644 --- a/pybeeb/Host/fsbbc.py +++ b/pybeeb/Host/fsbbc.py @@ -18,6 +18,10 @@ class BBCFileNotFoundError(BBCError): pass +class BBCDirNotFoundError(BBCFileNotFoundError): + pass + + class BBCNoHandlesError(BBCError): pass @@ -80,6 +84,7 @@ def __init__(self, fs, native_name, parent): self.name = name self.fullpath_native = None + self.fullpath = self.fs.join(parent.fullpath, name) if parent is not None: self.fullpath_native = os.path.join(parent.fullpath_native, native_name) @@ -229,6 +234,10 @@ def files(self): if exc.errno == errno.ENOENT: # FIXME: Find the error number raise BBCFileNotFoundError(0, "File '%s' not found" % (self.name,)) + if exc.errno == errno.ENOTDIR: + # FIXME: Find the error number + raise BBCDirNotFoundError(0, "Directory '%s' not found" % (self.name,)) + raise files = {} #print("Files in %r (%r)" % (self.fullpath, self.fullpath_native)) @@ -429,7 +438,7 @@ def split(self, path): if part[-1] != '$': parts = parts[:-1] else: - part.append('^') + parts.append('^') else: parts.append(part) return parts @@ -460,7 +469,11 @@ def cwd(self): @cwd.setter def cwd(self, value): - self._cwd = self.canonicalise(value) + dirent = self.find(value) + if dirent.objtype != 2: + # FIXME: Find the error number + raise BBCDirNotFoundError(0, "'%s' is not a directory" % (dirent.fullpath,)) + self._cwd = dirent.fullpath def dirname(self, path): parts = self.split(path) diff --git a/pybeeb/Host/hostfs.py b/pybeeb/Host/hostfs.py index ae6fa80..3f96469 100644 --- a/pybeeb/Host/hostfs.py +++ b/pybeeb/Host/hostfs.py @@ -2,7 +2,7 @@ Implementations of the OS interfaces which communicate with the host (file system specific) """ -from .base import OSInterface, OSFILE, OSFIND, OSBGET, OSBPUT, OSARGS, OSFSC, OSBYTE, BBCError +from .base import OSInterface, OSFILE, OSFIND, OSBGET, OSBPUT, OSARGS, OSFSC, OSBYTE, OSCLI, BBCError from .fsbbc import FS, BBCFileNotFoundError, open_in, open_out @@ -485,6 +485,19 @@ def osbyte_eof(self, a, x, y, pb): return True +class OSCLIhost(OSCLI): + + def __init__(self, fs): + super(OSCLIhost, self).__init__() + self.fs = fs + + self.commands_dispatch['DIR'] = self.cmd_dir + + def cmd_dir(self, args, pb): + self.fs.cwd = args + return True + + def host_fs_interfaces(basedir): """ Construct a list of OS interfaces for filesystems, using a host base directory. @@ -498,4 +511,5 @@ def host_fs_interfaces(basedir): lambda: OSARGShost(fs), lambda: OSFSChost(fs), lambda: OSBYTEhost(fs), + lambda: OSCLIhost(fs), ] From d69f5bc16230c026f8d6f0218076e40c04a1b82b Mon Sep 17 00:00:00 2001 From: Charles Ferguson <gerph@gerph.org> Date: Sat, 23 Dec 2023 12:27:09 +0000 Subject: [PATCH 49/65] Fix for Python 3 support in the Host/base.py module. Python 3 support had been broken when the CLI handling had been reworked. --- pybeeb/Host/base.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pybeeb/Host/base.py b/pybeeb/Host/base.py index 3078648..608e0f4 100644 --- a/pybeeb/Host/base.py +++ b/pybeeb/Host/base.py @@ -258,21 +258,21 @@ def call(self, pb): while cli[0:1] in (b'*', b' '): cli = cli[1:] - cmd = [] + cmd = bytearray() args = '' abbrev = False for index, c in enumerate(cli): - if c == ' ': + if c == 32: args = cli[index + 1:] break - if c == '.': + if c == ord('.'): args = cli[index + 1:] abbrev = True break - cmd.append(c.upper()) + cmd.append(c) dispatch = None - command = ''.join(cmd) + command = bytes(cmd).upper() #print("CMD: %r (abbrev=%s), args: %r" % (command, abbrev, args)) if abbrev: if not command: From 8849c816d5426a733e716939bde5a21b3509f7ea Mon Sep 17 00:00:00 2001 From: Charles Ferguson <gerph@gerph.org> Date: Sat, 23 Dec 2023 12:27:47 +0000 Subject: [PATCH 50/65] Update documentation to reflect current state. The documentation has been updated to reflect how the code has changed to focus on the new hooking system and the ability to interact with the host system. The old code has been moved to PyBeebMinimal.py as part of this. --- Makefile | 2 +- PyBeeb.py | 162 +++++++++++++++++++++++++++---------------- PyBeebMinimal.py | 84 ++++++++++++++++++++++ PyBeebU.py | 124 --------------------------------- README.md | 91 +++++++++++++++++++----- tests/HelloWorld,ffb | Bin 0 -> 21 bytes 6 files changed, 259 insertions(+), 204 deletions(-) create mode 100755 PyBeebMinimal.py delete mode 100755 PyBeebU.py create mode 100644 tests/HelloWorld,ffb diff --git a/Makefile b/Makefile index 857b477..f2d5cf1 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,7 @@ coverage_unittest_disassemble: ./coverage_run.py --module DisassembleTest coverage_inttest_pybeebu: - ./coverage_run.py --module PyBeebU < /dev/null + ./coverage_run.py --module PyBeeb < /dev/null coverage: \ coverage_clear \ diff --git a/PyBeeb.py b/PyBeeb.py index 4229629..37e4891 100755 --- a/PyBeeb.py +++ b/PyBeeb.py @@ -1,84 +1,124 @@ #!/usr/bin/env python ''' Created on 12 Oct 2011 +Updated on 09 Dec 2023 -@author: chris.whitworth +@author: chris.whitworth, gerph ''' -import os + import sys -import pybeeb.CPU.Memory as Memory -import pybeeb.CPU.Registers as Registers -import pybeeb.CPU.AddressDispatcher as AddressDispatcher -import pybeeb.CPU.Writeback as Writeback -import pybeeb.CPU.ExecutionUnit as ExecutionUnit -import pybeeb.CPU.Dispatch as Dispatch -import pybeeb.CPU.InstructionDecoder as Decoder -import pybeeb.Debugging.Combiner -import pybeeb.Debugging.Writeback -import pybeeb.Debugging.ExecutionUnit -import pybeeb.BBCMicro.System -import pybeeb - -DecodeFilename = os.path.join(os.path.dirname(pybeeb.__file__), "insts.csv") + +from pybeeb.Emulation import Pb, PbError, PbConstants +from pybeeb.Host import (BBCError, InputEOFError, OSInterface, + OSCLI, OSBYTE, OSFILE, OSFIND, OSARGS, OSBPUT, OSBGET, OSGBPB, OSFSC) +from pybeeb.Host.hosttty import OSWRCHtty, OSRDCHtty, OSWORDtty, OSBYTEtty +from pybeeb.Host.hostfs import host_fs_interfaces class BBC(object): - def __init__(self, pcTrace = False, verbose = False): - self.mem = Memory.Memory() - self.reg = Registers.RegisterBank() - addrDispatch = AddressDispatcher.AddressDispatcher(self.mem, self.reg) + def __init__(self, pcTrace=False, verbose=False): + self.pb = Pb() - execDispatch = ExecutionUnit.ExecutionDispatcher(self.mem,self.reg) - execLogger = pybeeb.Debugging.ExecutionUnit.LoggingExecutionUnit() - combinedExec = pybeeb.Debugging.Combiner.Dispatcher( (execLogger, execDispatch) ) + def go(self, syscalls): + try: + # Register the syscall execution entry points + hooks = [] + for addr, func in syscalls: + hooks.append(self.pb.hook_add(PbConstants.PB_HOOK_CODE, + func, begin=addr, end=addr + 1)) - writebackDispatch = Writeback.Dispatcher(self.mem,self.reg) - writebackLogger = pybeeb.Debugging.Writeback.LoggingDispatcher() - combinedWriteback = pybeeb.Debugging.Combiner.Dispatcher( (writebackLogger, writebackDispatch) ) + self.pb.emu_start(self.pb.reg_read(PbConstants.PB_6502_REG_PC), -2) + finally: + # Deregister the entry points + for hook in hooks: + self.pb.hook_del(hook) - decoder = Decoder.Decoder(DecodeFilename) - self.pcTrace = pcTrace - self.verbose = verbose +class OSCLIquit(OSCLI): - dispatch = None - if verbose: - dispatch = Dispatch.Dispatcher(decoder, addrDispatch, - combinedExec, combinedWriteback, - self.mem, self.reg) - else: - dispatch = Dispatch.Dispatcher(decoder, addrDispatch, - execDispatch, writebackDispatch, - self.mem, self.reg) + def __init__(self, *args, **kwargs): + super(OSCLIquit, self).__init__(*args, **kwargs) - self.bbc = pybeeb.BBCMicro.System.Beeb(dispatch) + self.commands_dispatch[b'QUIT'] = self.cmd_quit - def go(self, syscalls): - instr = 0 - # NOTE: We only support a single handler per address. - syscalls = dict(syscalls) + def cmd_quit(self, args, pb): + sys.exit() - while True: - if self.pcTrace: - print "%s: PC: %s" % (instr, hex(self.reg.pc)) - instr += 1 - if not self.pcTrace and not self.verbose: - if self.reg.pc in syscalls.keys(): - syscalls[self.reg.pc](self.reg, self.mem) +class OSBYTEversion(OSBYTE): - self.bbc.tick() + def __init__(self): + super(OSBYTEversion, self).__init__() - if self.verbose: - self.reg.status() + self.dispatch[(0x00, 0x00)] = self.osbyte_osversion_error -def OS_WRCH(reg,mem): sys.stdout.write(chr(reg.a)) -def OS_RDCH(reg,mem): print "OS_RDCH" # Could inject keypresses here maybe? + def osbyte_osversion_error(self, a, x, y, pb): + raise BBCError(247, "OS 1.20 (PyBeeb)") + + +def main(): + + def trace(pb, address, size, user_data): + data = pb.mem_read(address, size) + execcode = ' '.join('%02X' % (b,) for b in data) + + (inst, formatted, params, comment) = pb.dis.disassemble(address) + print("&%04X: %-10s : %s %s" % (address, execcode, inst, formatted)) + + def mem_hook(pb, access, address, size, value, user_data): + print("Access %s of &%04x, size %-3i from &%04x" % ('READ' if access == PbConstants.PB_MEM_READ else 'WRITE', + address, size, + pb.reg_read(PbConstants.PB_6502_REG_PC))) -if __name__ == "__main__": - OS_WRCH_LOC = 0xe0a4 - OS_RDCH_LOC = 0xdec5 - syscalls = [ (OS_WRCH_LOC, OS_WRCH), - (OS_RDCH_LOC, OS_RDCH) ] bbc = BBC() - bbc.go(syscalls) + + # Trace all the ROM execution + #bbc.pb.hook_add(PbConstants.PB_HOOK_CODE, trace, begin=0x8000, end=0xC000) + + # Report memory reads and writes around PAGE + #bbc.pb.hook_add(PbConstants.PB_HOOK_MEM_READ | PbConstants.PB_HOOK_MEM_WRITE, mem_hook, begin=0xe00, end=0xe01) + + # Report memory reads and writes anywhere between the PAGE and HIMEM (video memory). + #bbc.pb.hook_add(PbConstants.PB_HOOK_MEM_READ | PbConstants.PB_HOOK_MEM_WRITE, mem_hook, begin=0xe00, end=0x7c00) + + interface_classes = [ + OSWRCHtty, + OSRDCHtty, + OSCLIquit, + OSBYTEversion, + OSWORDtty, + OSBYTEtty, + ] + host_fs_interfaces('.') + try: + syscalls = [] + interfaces = [] + for cls in interface_classes: + interface = cls() + interface.start() + interfaces.append(interface) + def hook(pb, address, size, user_data, interface=interface): + try: + #print("Call interface %r" % (interface,)) + handled = interface.call(pb) + #print(" handled = %r" % (handled,)) + if handled: + pb.regs.pc = pb.dispatch.pullWord() + 1 + except BBCError as exc: + pb.memory.writeBytes(0x100, bytearray([0, exc.errnum])) + pb.memory.writeBytes(0x100 + 2, bytearray(exc.errmess.encode('latin-1'))) + pb.regs.pc = 0x100 + + syscalls.append((interface.code, hook)) + + bbc.go(syscalls) + + except InputEOFError as exc: + print("\nEOF") + + finally: + for interfaces in reversed(interfaces): + interface.stop() + + +if __name__ == "__main__": + main() diff --git a/PyBeebMinimal.py b/PyBeebMinimal.py new file mode 100755 index 0000000..e2db2f7 --- /dev/null +++ b/PyBeebMinimal.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python +''' +Created on 12 Oct 2011 + +@author: chris.whitworth +''' +import os +import sys +import pybeeb.CPU.Memory as Memory +import pybeeb.CPU.Registers as Registers +import pybeeb.CPU.AddressDispatcher as AddressDispatcher +import pybeeb.CPU.Writeback as Writeback +import pybeeb.CPU.ExecutionUnit as ExecutionUnit +import pybeeb.CPU.Dispatch as Dispatch +import pybeeb.CPU.InstructionDecoder as Decoder +import pybeeb.Debugging.Combiner +import pybeeb.Debugging.Writeback +import pybeeb.Debugging.ExecutionUnit +import pybeeb.BBCMicro.System +import pybeeb + +DecodeFilename = os.path.join(os.path.dirname(pybeeb.__file__), "insts.csv") + + +class BBC(object): + def __init__(self, pcTrace = False, verbose = False): + self.mem = Memory.Memory() + self.reg = Registers.RegisterBank() + addrDispatch = AddressDispatcher.AddressDispatcher(self.mem, self.reg) + + execDispatch = ExecutionUnit.ExecutionDispatcher(self.mem,self.reg) + execLogger = pybeeb.Debugging.ExecutionUnit.LoggingExecutionUnit() + combinedExec = pybeeb.Debugging.Combiner.Dispatcher( (execLogger, execDispatch) ) + + writebackDispatch = Writeback.Dispatcher(self.mem,self.reg) + writebackLogger = pybeeb.Debugging.Writeback.LoggingDispatcher() + combinedWriteback = pybeeb.Debugging.Combiner.Dispatcher( (writebackLogger, writebackDispatch) ) + + decoder = Decoder.Decoder(DecodeFilename) + + self.pcTrace = pcTrace + self.verbose = verbose + + dispatch = None + if verbose: + dispatch = Dispatch.Dispatcher(decoder, addrDispatch, + combinedExec, combinedWriteback, + self.mem, self.reg) + else: + dispatch = Dispatch.Dispatcher(decoder, addrDispatch, + execDispatch, writebackDispatch, + self.mem, self.reg) + + self.bbc = pybeeb.BBCMicro.System.Beeb(dispatch) + + def go(self, syscalls): + instr = 0 + # NOTE: We only support a single handler per address. + syscalls = dict(syscalls) + + while True: + if self.pcTrace: + print "%s: PC: %s" % (instr, hex(self.reg.pc)) + instr += 1 + + if not self.pcTrace and not self.verbose: + if self.reg.pc in syscalls.keys(): + syscalls[self.reg.pc](self.reg, self.mem) + + self.bbc.tick() + + if self.verbose: + self.reg.status() + +def OS_WRCH(reg,mem): sys.stdout.write(chr(reg.a)) +def OS_RDCH(reg,mem): print("OS_RDCH") # Could inject keypresses here maybe? + +if __name__ == "__main__": + OS_WRCH_LOC = 0xe0a4 + OS_RDCH_LOC = 0xdec5 + syscalls = [ (OS_WRCH_LOC, OS_WRCH), + (OS_RDCH_LOC, OS_RDCH) ] + bbc = BBC() + bbc.go(syscalls) diff --git a/PyBeebU.py b/PyBeebU.py deleted file mode 100755 index 537b7b4..0000000 --- a/PyBeebU.py +++ /dev/null @@ -1,124 +0,0 @@ -#!/usr/bin/env python -''' -Created on 12 Oct 2011 -Updated on 09 Dec 2023 - -@author: chris.whitworth, gerph -''' - -import sys - -from pybeeb.Emulation import Pb, PbError, PbConstants -from pybeeb.Host import (BBCError, InputEOFError, OSInterface, - OSCLI, OSBYTE, OSFILE, OSFIND, OSARGS, OSBPUT, OSBGET, OSGBPB, OSFSC) -from pybeeb.Host.hosttty import OSWRCHtty, OSRDCHtty, OSWORDtty, OSBYTEtty -from pybeeb.Host.hostfs import host_fs_interfaces - - -class BBC(object): - def __init__(self, pcTrace=False, verbose=False): - self.pb = Pb() - - def go(self, syscalls): - try: - # Register the syscall execution entry points - hooks = [] - for addr, func in syscalls: - hooks.append(self.pb.hook_add(PbConstants.PB_HOOK_CODE, - func, begin=addr, end=addr + 1)) - - self.pb.emu_start(self.pb.reg_read(PbConstants.PB_6502_REG_PC), -2) - finally: - # Deregister the entry points - for hook in hooks: - self.pb.hook_del(hook) - - -class OSCLIquit(OSCLI): - - def __init__(self, *args, **kwargs): - super(OSCLIquit, self).__init__(*args, **kwargs) - - self.commands_dispatch['QUIT'] = self.cmd_quit - - def cmd_quit(self, args, pb): - sys.exit() - - -class OSBYTEversion(OSBYTE): - - def __init__(self): - super(OSBYTEversion, self).__init__() - - self.dispatch[(0x00, 0x00)] = self.osbyte_osversion_error - - def osbyte_osversion_error(self, a, x, y, pb): - raise BBCError(247, "OS 1.20 (PyBeeb)") - - -def main(): - - def trace(pb, address, size, user_data): - data = pb.mem_read(address, size) - execcode = ' '.join('%02X' % (b,) for b in data) - - (inst, formatted, params, comment) = pb.dis.disassemble(address) - print("&%04X: %-10s : %s %s" % (address, execcode, inst, formatted)) - - def mem_hook(pb, access, address, size, value, user_data): - print("Access %s of &%04x, size %-3i from &%04x" % ('READ' if access == PbConstants.PB_MEM_READ else 'WRITE', - address, size, - pb.reg_read(PbConstants.PB_6502_REG_PC))) - - bbc = BBC() - - # Trace all the ROM execution - #bbc.pb.hook_add(PbConstants.PB_HOOK_CODE, trace, begin=0x8000, end=0xC000) - - # Report memory reads and writes around PAGE - #bbc.pb.hook_add(PbConstants.PB_HOOK_MEM_READ | PbConstants.PB_HOOK_MEM_WRITE, mem_hook, begin=0xe00, end=0xe01) - - # Report memory reads and writes anywhere between the PAGE and HIMEM (video memory). - #bbc.pb.hook_add(PbConstants.PB_HOOK_MEM_READ | PbConstants.PB_HOOK_MEM_WRITE, mem_hook, begin=0xe00, end=0x7c00) - - interface_classes = [ - OSWRCHtty, - OSRDCHtty, - OSCLIquit, - OSBYTEversion, - OSWORDtty, - OSBYTEtty, - ] + host_fs_interfaces('.') - try: - syscalls = [] - interfaces = [] - for cls in interface_classes: - interface = cls() - interface.start() - interfaces.append(interface) - def hook(pb, address, size, user_data, interface=interface): - try: - #print("Call interface %r" % (interface,)) - handled = interface.call(pb) - #print(" handled = %r" % (handled,)) - if handled: - pb.regs.pc = pb.dispatch.pullWord() + 1 - except BBCError as exc: - pb.memory.writeBytes(0x100, bytearray([0, exc.errnum])) - pb.memory.writeBytes(0x100 + 2, bytearray(exc.errmess.encode('latin-1'))) - pb.regs.pc = 0x100 - - syscalls.append((interface.code, hook)) - - bbc.go(syscalls) - - except InputEOFError as exc: - print("\nEOF") - - finally: - for interfaces in reversed(interfaces): - interface.stop() - - -if __name__ == "__main__": - main() diff --git a/README.md b/README.md index e6659f7..0a13eab 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,73 @@ -This is a (partial) emulation of a BBC Micro in Python - it includes emulation -of a 6502 CPU and enough supporting hardware to boot MOS 1.2 and get to the -BASIC prompt. - -There's no keyboard or display (or indeed, any other I/O) support as yet - -at the moment, output is done by hooking the `OS_WRCH` syscall and -printing the contents of the A register to `stdout`. The emulator will -essentially hang when it gets to an `OS_RDCH` as it's waiting for a keypress -that will never come. - -To run the emulator, run `python PyBeeb.py`. - -I've tested it with Python 2.7; it won't work with Python 3, I'm afraid. - -It's possible to replace parts of the CPU with custom implementations; for -example, see `Disassembler.py` for an example of how to replace the execution -unit to turn the emulator into a disassembler. This is also used for the -verbose/PC-trace debugging instrumentation. +# PyBeeb - A simple BBC Micro emulator in Python + +## Summary + +This is a (partial) emulation of a BBC Micro in Python - it includes emulation +of a 6502 CPU and enough supporting hardware to boot MOS 1.2 and get to the +BASIC prompt. + +The emulator is intended for experimentation and learning about the operation +of a simple CPU, within a wimpler Python environment. The emulator has the +ability to 'hook' addresses within the 6502 code and either trace their +use, or modify the behaviour, in Python. + +## Usage + +The emulator can be run with `python PyBeeb.py`. This will start the emulator +running, booting the BBC MOS and entering BBC BASIC. The emulator provides +default hooks to allow the terminal input to be passed to the keyboard reading +code, VDU output will be written to the terminal output. + +Simple hooks are provided for the filesystem interfaces, allowing access +to files within the current working directory in the host system. + +Within the emulator, running BASIC, you can write programs and load and save +files. There is no video or sound system attached in this emulation, so any +graphics will not be displayed, and sound (other than the terminal beeb) will +not be heard. + + +### Example usage + +The emulator runs at a BASIC prompt by default, and you can run commands, such +as printing messages: + + PRINT "Hello world" + +The current directory can be listed with `*CAT` or `*.`: + + *cat + +Programs can be loaded and saved with `LOAD` and `SAVE`. On the BBC file paths +are separated by a `.` character (not the `/` that you might be used to on +unix-like systems, or the `\\` used by Windows and DOS systems). An example +program can be found in the `tests` directory, which you can run: + + LOAD "Tests.helloworld" + RUN + +To quit the emulator, use `*QUIT`: + + *quit + +## Host hooks + +Extensions to the BBC system are provided through hooks which can be registered +with the emulator. The emulation system, and its hooks, are based around the +spirit of the Unicorn engine emulator. Hooks can be registered for code +execution, and memory accesses. + +The `PyBeeb.py` tool contains commented out code which can be enabled to use +these hooks directly. The example hooks allow code to be traced - each instruction +executed will be disassembled and displayed - and to report on memory accesses +in different areas of memory. + +The `pybeeb.Host` package contains a number of implementations of hooked routines +which can be used to replace or augment the standard MOS routines. This package +contains base classess which interpret the interfaces in the `base` module, and +concrete classes within the `hostfs` and `hosttty` modules. These latter modules +provide the file system and terminal I/O. + +The `PyBeeb.py` tool includes two simple examples of these extensions, to provide +more information in `*FX0` (the system version), and to allow the emulator to be +quit with `*Quit`. diff --git a/tests/HelloWorld,ffb b/tests/HelloWorld,ffb new file mode 100644 index 0000000000000000000000000000000000000000..f6d479f5315aebed9ed5c9c3e41bd7e016a9819f GIT binary patch literal 21 ccmd;O;1d3*<dK?_ldn*oUzC%gsKomp06^{r$p8QV literal 0 HcmV?d00001 From e6c0e369b4ddfea8d461d0595efd4a1907da7755 Mon Sep 17 00:00:00 2001 From: Charles Ferguson <gerph@gerph.org> Date: Sat, 23 Dec 2023 12:55:58 +0000 Subject: [PATCH 51/65] Fixes for the Coverage runs. Coverage runs of the Memory tests hadn't been working at all. They were not invoking the unittest on the module. We now correctly invoke that and get better coverage because of it. The coverage had been confused on MacOS because PyBeeb.py and pybeeb/__init__.py are effectively the same module, so we were getting other references to modules that weren't really there. To avoid this problem, and to make it easier to understand the difference between the tool and the package, the command line program has been renamed to `RunBeeb.py`. --- Makefile | 19 ++++++++++++++++--- MemoryTests.py | 11 +++++++---- README.md | 6 +++--- PyBeeb.py => RunBeeb.py | 0 PyBeebMinimal.py => RunBeebMinimal.py | 0 5 files changed, 26 insertions(+), 10 deletions(-) rename PyBeeb.py => RunBeeb.py (100%) rename PyBeebMinimal.py => RunBeebMinimal.py (100%) diff --git a/Makefile b/Makefile index f2d5cf1..ba0aa62 100644 --- a/Makefile +++ b/Makefile @@ -14,12 +14,25 @@ coverage_unittest_memory: coverage_unittest_disassemble: ./coverage_run.py --module DisassembleTest -coverage_inttest_pybeebu: - ./coverage_run.py --module PyBeeb < /dev/null +coverage_inttest: \ + coverage_inttest_pybeeb_invoke \ + coverage_inttest_pybeeb_fs \ + coverage_inttest_pybeeb_commands + +# NOTE: None of these tests check the output to confirm that we're doing the right thing. +# Simple invocation test +coverage_inttest_pybeeb_invoke: + ./coverage_run.py --module RunBeeb < /dev/null + +coverage_inttest_pybeeb_fs: + printf '*.\n*. tests\nLOAD "Tests.helloworld"\nRUN' | ./coverage_run.py --module RunBeeb + +coverage_inttest_pybeeb_commands: + printf '*FX0\n*QUIT\n' | ./coverage_run.py --module RunBeeb coverage: \ coverage_clear \ coverage_unittest_memory \ coverage_unittest_disassemble \ - coverage_inttest_pybeebu + coverage_inttest ./coverage_run.py --coverage-report diff --git a/MemoryTests.py b/MemoryTests.py index fcd3cab..e6f2275 100755 --- a/MemoryTests.py +++ b/MemoryTests.py @@ -16,6 +16,7 @@ def readByte(self, address): def writeByte(self, address, value): self.lastByteWritten = (address, value) + class MemoryTestsSimple(unittest.TestCase): def setUp(self): self.mem = pybeeb.CPU.Memory.Memory() @@ -29,11 +30,12 @@ def test_writeEveryByte(self): self.mem.writeByte(address, 1) self.assertEqual(self.mem.readByte(address), 1) + class MappingTestSimple(unittest.TestCase): def setUp(self): self.mem = pybeeb.CPU.Memory.Memory() self.mapper = MockMapper() - self.mem.map( (0, 0x100), self.mapper) + self.mem.map((0, 0xFF), self.mapper) def test_readInRange(self): for address in range(0x100): @@ -55,6 +57,7 @@ def test_writeOutOfRange(self): self.mem.writeByte(address, (address & 0xff) ^ 0xff) self.assertEqual(self.mapper.lastByteWritten, (None, None)) + class OverlaidMappingTests(unittest.TestCase): def setUp(self): self.mem = pybeeb.CPU.Memory.Memory() @@ -62,8 +65,8 @@ def setUp(self): self.firstMapper = MockMapper() self.secondMapper = MockMapper() - self.mem.map( (0, 0x200), self.firstMapper) - self.mem.map( (0x100, 0x300), self.secondMapper) + self.mem.map((0, 0x200), self.firstMapper) + self.mem.map((0x100, 0x300), self.secondMapper) def test_readInFirstMap(self): for address in range(0, 0x100): @@ -103,7 +106,7 @@ def test_writeInSecondMap(self): def main(): - unittest.main() + unittest.main(module=__name__) if __name__ == '__main__': diff --git a/README.md b/README.md index 0a13eab..a489b57 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ use, or modify the behaviour, in Python. ## Usage -The emulator can be run with `python PyBeeb.py`. This will start the emulator +The emulator can be run with `python RunBeeb.py`. This will start the emulator running, booting the BBC MOS and entering BBC BASIC. The emulator provides default hooks to allow the terminal input to be passed to the keyboard reading code, VDU output will be written to the terminal output. @@ -57,7 +57,7 @@ with the emulator. The emulation system, and its hooks, are based around the spirit of the Unicorn engine emulator. Hooks can be registered for code execution, and memory accesses. -The `PyBeeb.py` tool contains commented out code which can be enabled to use +The `RunBeeb.py` tool contains commented out code which can be enabled to use these hooks directly. The example hooks allow code to be traced - each instruction executed will be disassembled and displayed - and to report on memory accesses in different areas of memory. @@ -68,6 +68,6 @@ contains base classess which interpret the interfaces in the `base` module, and concrete classes within the `hostfs` and `hosttty` modules. These latter modules provide the file system and terminal I/O. -The `PyBeeb.py` tool includes two simple examples of these extensions, to provide +The `RunBeeb.py` tool includes two simple examples of these extensions, to provide more information in `*FX0` (the system version), and to allow the emulator to be quit with `*Quit`. diff --git a/PyBeeb.py b/RunBeeb.py similarity index 100% rename from PyBeeb.py rename to RunBeeb.py diff --git a/PyBeebMinimal.py b/RunBeebMinimal.py similarity index 100% rename from PyBeebMinimal.py rename to RunBeebMinimal.py From 30cf7b99c5c12fa67637cdc631fd9d6c073becb0 Mon Sep 17 00:00:00 2001 From: Charles Ferguson <gerph@gerph.org> Date: Sat, 23 Dec 2023 14:08:48 +0000 Subject: [PATCH 52/65] Updated Python 3 support to cover filesystem interfaces. The filesystem interfaces should now be reporting the filenames properly to the BBC and back out again to the host filesystem, when used in both Python 2 and Python 3. --- Makefile | 4 + pybeeb/Host/base.py | 8 +- pybeeb/Host/fsbbc.py | 175 +++++++++++++++++++++++------------------- pybeeb/Host/hostfs.py | 13 ++-- pybeeb/MOS.py | 16 +++- tests/ReadFile,ffb | Bin 0 -> 77 bytes tests/hello-basic | Bin 0 -> 8 bytes 7 files changed, 129 insertions(+), 87 deletions(-) create mode 100644 tests/ReadFile,ffb create mode 100644 tests/hello-basic diff --git a/Makefile b/Makefile index ba0aa62..d4abf56 100644 --- a/Makefile +++ b/Makefile @@ -17,6 +17,7 @@ coverage_unittest_disassemble: coverage_inttest: \ coverage_inttest_pybeeb_invoke \ coverage_inttest_pybeeb_fs \ + coverage_inttest_pybeeb_stream \ coverage_inttest_pybeeb_commands # NOTE: None of these tests check the output to confirm that we're doing the right thing. @@ -27,6 +28,9 @@ coverage_inttest_pybeeb_invoke: coverage_inttest_pybeeb_fs: printf '*.\n*. tests\nLOAD "Tests.helloworld"\nRUN' | ./coverage_run.py --module RunBeeb +coverage_inttest_pybeeb_stream: + printf '*dir tests\nCHAIN "readfile"\n' | ./coverage_run.py --module RunBeeb + coverage_inttest_pybeeb_commands: printf '*FX0\n*QUIT\n' | ./coverage_run.py --module RunBeeb diff --git a/pybeeb/Host/base.py b/pybeeb/Host/base.py index 608e0f4..f116257 100644 --- a/pybeeb/Host/base.py +++ b/pybeeb/Host/base.py @@ -75,7 +75,10 @@ class BBCError(Exception): def __init__(self, errnum, errmess): self.errnum = errnum - self.errmess = errmess + if isinstance(errmess, bytes): + self.errmess = errmess.decode('latin-1') + else: + self.errmess = errmess super(BBCError, self).__init__(errmess, errnum) @@ -261,7 +264,8 @@ def call(self, pb): cmd = bytearray() args = '' abbrev = False - for index, c in enumerate(cli): + for index, c in enumerate(bytearray(cli)): + #print("cli = %r, c = %r" % (cli, c)) if c == 32: args = cli[index + 1:] break diff --git a/pybeeb/Host/fsbbc.py b/pybeeb/Host/fsbbc.py index dc0994e..e41a9d9 100644 --- a/pybeeb/Host/fsbbc.py +++ b/pybeeb/Host/fsbbc.py @@ -34,7 +34,7 @@ class DirectoryEntry(object): default_loadaddr = 0x00000000 default_execaddr = 0x00000000 default_attributes = 0b00110011 - hexdigits = '0123456789abcdef' + hexdigits = b'0123456789abcdef' stat_read_mask = stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH stat_write_mask = stat.S_IWUSR | stat.S_IWGRP | stat.S_IWOTH @@ -52,7 +52,7 @@ def __init__(self, fs, native_name, parent): name = self.fs.decode_from_filesystem(native_name) explicit_loadexec = False if len(name) > 18 and \ - name[-9] == ',' and name[-18] == ',' and \ + name[-9:-8] == b',' and name[-18:-17] == b',' and \ all(c in self.hexdigits for c in name[-8:]) and \ all(c in self.hexdigits for c in name[-17:-9]): # 1+8+1+8 for ,llllllll,eeeeeeee @@ -67,13 +67,13 @@ def __init__(self, fs, native_name, parent): ext = None #print("Checking name %r" % (name,)) if len(name) > 4 and \ - name[-4] == ',' and all(c in self.hexdigits for c in name[-3:]): + name[-4:-3] == b',' and all(c in self.hexdigits for c in name[-3:]): ext = name[-4:] elif len(name) > 4 and \ - name[-4] == '/': + name[-4:-3] == b'/': # The name has already been decoded from the filesystem, so . => /. - ext = '.' + name[-3:] + ext = b'.' + name[-3:] if ext: loadexec = self.fs.loadexec_from_extension.get(ext, None) @@ -84,7 +84,7 @@ def __init__(self, fs, native_name, parent): self.name = name self.fullpath_native = None - self.fullpath = self.fs.join(parent.fullpath, name) + self.fullpath = self.fs.join(parent.fullpath, self.name) if parent is not None: self.fullpath_native = os.path.join(parent.fullpath_native, native_name) @@ -110,7 +110,7 @@ def __init__(self, fs, native_name, parent): else: # When we don't know the filetype, we leave it set to 0 - if native_name == '$': + if native_name == b'$': # This is the root entry, so fake as a directory self.objtype = 2 else: @@ -217,14 +217,24 @@ def __init__(self, fs, name, parent): if parent: self.fullpath = self.fs.join(parent.fullpath, name) else: - self.fullpath = self.fs.join("$", name) + self.fullpath = self.fs.join(b'$', name) if parent: - self.fullpath_native = os.path.join(parent.fullpath_native, name) + self.fullpath_native = os.path.join(parent.fullpath_native, name.decode('latin-1')) else: self.fullpath_native = self.fs.basedir self._files = None + def __repr__(self): + if self._files: + files = "files=%s" % (len(self._files),) + else: + files = "files uncached" + return "<{}(name={!r}, native={!r}, {}>".format(self.__class__.__name__, + self.fullpath, + self.fullpath_native, + files) + @property def files(self): if not self._files: @@ -233,10 +243,10 @@ def files(self): except OSError as exc: if exc.errno == errno.ENOENT: # FIXME: Find the error number - raise BBCFileNotFoundError(0, "File '%s' not found" % (self.name,)) + raise BBCFileNotFoundError(0, b"File '%s' not found" % (self.name,)) if exc.errno == errno.ENOTDIR: # FIXME: Find the error number - raise BBCDirNotFoundError(0, "Directory '%s' not found" % (self.name,)) + raise BBCDirNotFoundError(0, b"Directory '%s' not found" % (self.name,)) raise files = {} @@ -258,7 +268,7 @@ def __getitem__(self, name): dirent = self.files.get(name.lower(), None) if dirent is None: # FIXME: Find the error number - raise BBCFileNotFoundError(0, "File '%s' not found" % (name,)) + raise BBCFileNotFoundError(0, b"File '%s' not found" % (name,)) return dirent @@ -321,21 +331,21 @@ class FS(object): An interface for accessing the filesystem. """ loadexec_to_extension = { - (None, 0xFFFF8023): '.bas', - (None, 0xFFFF801F): '.bas', - (0xFFFF8000, 0xFFFF8000): '.rom', - (0xFFFFFFFF, 0xFFFFFFFF): '.txt', + (None, 0xFFFF8023): b'.bas', + (None, 0xFFFF801F): b'.bas', + (0xFFFF8000, 0xFFFF8000): b'.rom', + (0xFFFFFFFF, 0xFFFFFFFF): b'.txt', } loadexec_from_extension = { - '.bas': (0xFFFF0E00, 0xFFFF8023), - '.rom': (0xFFFF8000, 0xFFFF8000), - '.txt': (0xFFFFFFFF, 0xFFFFFFFF), + b'.bas': (0xFFFF0E00, 0xFFFF8023), + b'.rom': (0xFFFF8000, 0xFFFF8000), + b'.txt': (0xFFFFFFFF, 0xFFFFFFFF), # NFS style RISC OS extensions - ',ffb': (0xFFFF0E00, 0xFFFF8023), # Tokenised BBC BASIC - ',fd1': (0xFFFFFFFF, 0xFFFFFFFF), # Detokenised BBC BASIC - ',fff': (0xFFFFFFFF, 0xFFFFFFFF), # Text - '.bbc': (0xFFFF8000, 0xFFFF8000), # BBC ROM + b',ffb': (0xFFFF0E00, 0xFFFF8023), # Tokenised BBC BASIC + b',fd1': (0xFFFFFFFF, 0xFFFFFFFF), # Detokenised BBC BASIC + b',fff': (0xFFFFFFFF, 0xFFFFFFFF), # Text + b'.bbc': (0xFFFF8000, 0xFFFF8000), # BBC ROM } open_loadaddr = 0xFFFFFFFF @@ -347,7 +357,7 @@ def __init__(self, basedir="."): self.cached = {} self.filehandles = {} self._next_filehandle = self.filehandle_max - self._cwd = '$' + self._cwd = b'$' try: self.native_uid = os.getuid() @@ -360,38 +370,48 @@ def __init__(self, basedir="."): def encode_to_filesystem(self, filename): """ Convert from a unicode string to something in the host filesystem. - """ - # FIXME: Perform some conversion on the character set + @param filename: BBC filename (latin-1) + + @return: Filesystem filename (unicode) + """ # In the filesystem a '/' is reported as a '.' - filename = filename.replace('/', '.') + filename = filename.replace(b'/', b'.') + + # Convert the filename into unicode format + filename = filename.decode('latin-1') return filename def decode_from_filesystem(self, filename): """ Convert from a host filesystem name to a unicode string for BBC. + + @param filename: Filesystem filename (unicode) + + @return: BBC filename (latin-1) """ - # FIXME: Perform some conversion on the character set + # Convert the filename into encoded format + filename = filename.encode('latin-1') # In the filesystem a '/' is reported as a '.' - filename = filename.replace('.', '/') + filename = filename.replace(b'.', b'/') return filename def join(self, *paths): - parts = ['$'] + parts = [b'$'] for path in paths: - if path is None or path == '$': - parts = ['$'] + if path is None or path == b'$': + parts = [b'$'] else: parts.append(path) - if '^' in parts: + if b'^' in parts: # Only go through the process of reconciling '^' if one was present - return self.canonicalise('.'.join(parts)) - return '.'.join(parts) + return self.canonicalise(b'.'.join(parts)) + return b'.'.join(parts) def generate_native_filename(self, name, loadaddr, execaddr, objtype): """ @@ -399,46 +419,44 @@ def generate_native_filename(self, name, loadaddr, execaddr, objtype): or the load/exec changed """ - # Do the basic conversion - new_name = self.encode_to_filesystem(name) - - if objtype == 2: - return new_name - - # Certain load/exec extensions are able to be converted through the mapping - ext = self.loadexec_to_extension.get((loadaddr, execaddr), None) - if not ext: - ext = self.loadexec_to_extension.get((loadaddr, None), None) + if objtype != 2: + # Certain load/exec extensions are able to be converted through the mapping + ext = self.loadexec_to_extension.get((loadaddr, execaddr), None) if not ext: - ext = self.loadexec_to_extension.get((None, execaddr), None) - if ext: - #print("ext name : %s / %s" % (new_name, ext)) - new_name = "%s%s" % (new_name, ext) - else: - # Load and exec address are required, so we need to put the long extension on - # Ensure the load and exec are the unsigned values: - if loadaddr < 0: - loadaddr += (1<<32) - loadaddr = loadaddr & 0xFFFFFFFF - if execaddr < 0: - execaddr += (1<<32) - execaddr = execaddr & 0xFFFFFFFF + ext = self.loadexec_to_extension.get((loadaddr, None), None) + if not ext: + ext = self.loadexec_to_extension.get((None, execaddr), None) + if ext: + #print("ext name : %s / %s" % (new_name, ext)) + name = b"%s%s" % (name, ext) + else: + # Load and exec address are required, so we need to put the long extension on + # Ensure the load and exec are the unsigned values: + if loadaddr < 0: + loadaddr += (1<<32) + loadaddr = loadaddr & 0xFFFFFFFF + if execaddr < 0: + execaddr += (1<<32) + execaddr = execaddr & 0xFFFFFFFF + + name = b'%s,%08x,%08x' % (name, loadaddr, execaddr) - new_name = '%s,%08x,%08x' % (new_name, loadaddr, execaddr) + # Do the basic conversion + new_name = self.encode_to_filesystem(name) return new_name def split(self, path): parts = [] - for part in path.split('.'): - if part == '$': - parts = ['$'] - elif part == '^': - if len(parts) > 1 and part[-1] != '^': - if part[-1] != '$': + for part in path.split(b'.'): + if part == b'$': + parts = [b'$'] + elif part == b'^': + if len(parts) > 1 and part[-1] != b'^': + if part[-1] != b'$': parts = parts[:-1] else: - parts.append('^') + parts.append(b'^') else: parts.append(part) return parts @@ -449,19 +467,19 @@ def canonicalise(self, path): if not path_parts: # This is the CWD parts = cwd_parts - elif path_parts and path_parts[0] == '$': + elif path_parts and path_parts[0] == b'$': # This is already rooted parts = path_parts else: - while path_parts and path_parts[0] == '^': + while path_parts and path_parts[0] == b'^': if cwd_parts: cwd_parts = cwd_parts[:-1] path_parts = path_parts[1:] if cwd_parts: parts = cwd_parts + path_parts else: - parts = ['$'] - return '.'.join(parts) + parts = [b'$'] + return b'.'.join(parts) @property def cwd(self): @@ -472,7 +490,7 @@ def cwd(self, value): dirent = self.find(value) if dirent.objtype != 2: # FIXME: Find the error number - raise BBCDirNotFoundError(0, "'%s' is not a directory" % (dirent.fullpath,)) + raise BBCDirNotFoundError(0, b"'%s' is not a directory" % (dirent.fullpath,)) self._cwd = dirent.fullpath def dirname(self, path): @@ -487,9 +505,9 @@ def leafname(self, path): def splitname(self, path): parts = self.split(path) - dirname = '.'.join(parts[:-1]) + dirname = b'.'.join(parts[:-1]) if not dirname: - dirname = "$" + dirname = b'$' leafname = parts[-1] return (dirname, leafname) @@ -506,7 +524,7 @@ def dir(self, path=None): if dir is None: (dirname, leafname) = self.splitname(path) #print(" dirname=%s leafname=%s" % (dirname, leafname)) - if leafname != '$': + if leafname != b'$': parent = self.dir(dirname) dir = Directory(self, leafname, parent) else: @@ -517,15 +535,18 @@ def dir(self, path=None): def find(self, path): path = self.canonicalise(path) + #print("find: path = %r" % (path,)) (dirname, leafname) = self.splitname(path) + #print("find: dirname = %r, leafname = %r" % (dirname, leafname)) dir = self.dir(dirname) + #print("find: dir = %r" % (dir,)) dirent = dir[leafname] return dirent def allocate_filehandle(self, bfh): if not self._next_filehandle: # FIXME: Fix error number - raise BBCNoHandlesError(0, "No more file handles") + raise BBCNoHandlesError(0, b"No more file handles") bfh.handle = self._next_filehandle self.filehandles[bfh.handle] = bfh @@ -559,7 +580,7 @@ def find_filehandle(self, handle): bfh = self.filehandles.get(handle, None) if not bfh: # FIXME: Fix error number - raise BBCBadHandleError(0, "Bad file handle") + raise BBCBadHandleError(0, b"Bad file handle") return bfh def filehandle_range(self): @@ -644,7 +665,7 @@ def open(self, filename, how): def close(self, handle): if handle == 0: # FIXME: Could make this work as on the BBC - raise BBCError(0, "Not closing all files") + raise BBCError(0, b"Not closing all files") bfh = self.find_filehandle(handle) bfh.close() diff --git a/pybeeb/Host/hostfs.py b/pybeeb/Host/hostfs.py index 3f96469..ddd6eb2 100644 --- a/pybeeb/Host/hostfs.py +++ b/pybeeb/Host/hostfs.py @@ -112,14 +112,15 @@ def load(self, filename, load_address, pb): Tuple of (info_type, info_load, info_exec, info_length, info_attr) if handled """ handle = None + #print("Load: %r" % (filename,)) try: (info_type, info_load, info_exec, info_length, info_attr) = self.fs.fileinfo(filename) if info_type == 0: # FIXME: Error number - raise BBCFileNotFoundError(0, "File not found") + raise BBCFileNotFoundError(0, b"File '%s' not found" % (filename,)) if info_type == 2: # FIXME: Error number - raise BBCFileNotFoundError(0, "Is a directory") + raise BBCFileNotFoundError(0, b"'%s' is a directory" % (filename,)) if load_address is None: load_address = info_load & 0xFFFF @@ -192,7 +193,7 @@ def osbget(self, fh, pb): data = self.fs.read(fh, 1) if not data: return -1 - return bytearray(data[0])[0] + return bytearray(data)[0] class OSBPUThost(OSBPUT): @@ -393,14 +394,14 @@ def cat(self, path, pb): longest_name = max(len(dirent.name) for dirent in files.values()) longest_name = max(10, longest_name) - pb.mos.write("Dir. %s\n\n" % (dir.fullpath,)) + pb.mos.write("Dir. %s\n\n" % (dir.fullpath.decode('latin-1'),)) ordered = sorted(files.items()) width = 40 # FIXME: Make the width configurable (or read from the mode vars?) x = 0 for key, dirent in ordered: - text = "%-*s " % (longest_name, dirent.name) + text = "%-*s " % (longest_name, dirent.name.decode('latin-1')) attr = [] if dirent.objtype == 2: attr.append('D') @@ -491,7 +492,7 @@ def __init__(self, fs): super(OSCLIhost, self).__init__() self.fs = fs - self.commands_dispatch['DIR'] = self.cmd_dir + self.commands_dispatch[b'DIR'] = self.cmd_dir def cmd_dir(self, args, pb): self.fs.cwd = args diff --git a/pybeeb/MOS.py b/pybeeb/MOS.py index 4f9281a..5133d05 100644 --- a/pybeeb/MOS.py +++ b/pybeeb/MOS.py @@ -5,6 +5,13 @@ from .Emulation import PbConstants, StackOverflowException, StackUnderflowException +# Python 2/3 support +try: + unicode +except: + unicode = str + + class ExecutionComplete(Exception): pass @@ -99,19 +106,24 @@ def osasci(self, c): def write(self, msg): if isinstance(msg, bytes): data = bytearray(msg) - elif isinstance(msg, str): + elif isinstance(msg, (str, unicode)): # Let's use latin-1 as our encoding for now. data = msg.encode('latin-1') data = bytearray(data) + elif isinstance(msg, bytearray): + data = msg for c in data: self.osasci(c) def writeraw(self, msg): if isinstance(msg, bytes): data = bytearray(msg) - elif isinstance(msg, str): + elif isinstance(msg, (str, unicode)): # Let's use latin-1 as our encoding for now. data = msg.encode('latin-1') data = bytearray(data) + elif isinstance(msg, bytearray): + data = msg + for c in data: self.oswrch(c) diff --git a/tests/ReadFile,ffb b/tests/ReadFile,ffb new file mode 100644 index 0000000000000000000000000000000000000000..923fc4c563c9a9684860b8715724670f75731230 GIT binary patch literal 77 zcmd;O;1bVNwe8bT%1F)0$=6LvEY3_;(&S|j;d`N+sj8!pTb!=K%OI!r9L%y+@&GAQ bR8r{qsG#KUt)$TXQOPYaGbc4giT6JMGG7-2 literal 0 HcmV?d00001 diff --git a/tests/hello-basic b/tests/hello-basic new file mode 100644 index 0000000000000000000000000000000000000000..f816ecda536336709a25e4efc9e9db0853e8ce8e GIT binary patch literal 8 PcmZQzQ_RoFN%a5#2Ppy^ literal 0 HcmV?d00001 From 312c229bcf7042858ec0f58a59e865ea908d81d8 Mon Sep 17 00:00:00 2001 From: Charles Ferguson <gerph@gerph.org> Date: Thu, 13 Jun 2024 15:54:45 +0100 Subject: [PATCH 53/65] Allow *Exec to work with the host readline; ctrl-c=>escape in RDCH. When *Exec is used and we're trying to read a line, don't call the host ReadLine interface. Instead we fall back to the standard ReadLine in the MOS which will read characters and insert them into the input from the file. When ctrl-c is pressed whilst waiting for a key press, we now treat this as an escape press. --- pybeeb/Host/base.py | 27 ++++++++++++++++++--------- pybeeb/Host/hosttty.py | 7 +++++++ 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/pybeeb/Host/base.py b/pybeeb/Host/base.py index f116257..876bfd2 100644 --- a/pybeeb/Host/base.py +++ b/pybeeb/Host/base.py @@ -182,11 +182,15 @@ class OSRDCH(OSInterface): vector = 0x0210 def call(self, pb): - ch = self.readc() - if ch is None: - return False + try: + ch = self.readc() + if ch is None: + return False + ch = ord(ch) + + except KeyboardInterrupt: + ch = 27 - ch = ord(ch) if ch == 27: pb.regs.carry = True @@ -221,11 +225,15 @@ def call(self, pb): # A character was already read return False - ch = self.readc() - if ch is None: - return False + try: + ch = self.readc() + if ch is None: + return False + ch = ord(ch) + + except KeyboardInterrupt: + ch = 27 - ch = ord(ch) if ch == 27: # Bit of a hack as we don't have interrupts # Set the escape flag @@ -307,6 +315,7 @@ def __init__(self): self.dispatch_default = self.osbyte def osbyte(self, a, x, y, pb): + #print("OSByte &%02x, %i, %i" % (a, x, y)) return False @@ -323,7 +332,7 @@ def __init__(self): def dispatch_parameters(self, pb): """ - Decode the paramters for the address. + Decode the parameters for the address. """ address = pb.regs.x | (pb.regs.y << 8) return [pb.regs.a, address, pb] diff --git a/pybeeb/Host/hosttty.py b/pybeeb/Host/hosttty.py index eba96cc..7b7f5f7 100644 --- a/pybeeb/Host/hosttty.py +++ b/pybeeb/Host/hosttty.py @@ -117,6 +117,13 @@ def osword_readline(self, a, address, pb): # C=1 if an ESCAPE condition terminated input. # Y contains line length, including carriage return if # used. + + # Check the exec handle first + exec_handle = pb.memory.readByte(0x256) + if exec_handle != 0: + # There's an exec in progress, so don't perform the host readline + return False + input_memory = pb.memory.readWord(address) maxline = pb.memory.readByte(address + 2) lowest = pb.memory.readByte(address + 3) From 29b11117b39eafb2190f0ea94bcb47a762b87522 Mon Sep 17 00:00:00 2001 From: Charles Ferguson <gerph@gerph.org> Date: Sun, 11 Jan 2026 01:14:02 +0000 Subject: [PATCH 54/65] Update CI to run on PRs --- .github/workflows/ci.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6ae9876..52fa70f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,13 +7,14 @@ name: Tests # Controls when the action will run. Triggers the workflow on: # * push on any branch. # * tag creation for tags beginning with a 'v' +# * pull requests on: push: branches: ["*"] tags: ["v*"] - # Pull request events happen on pull request state transitions, so we probably don't want this here. - #pull_request: - # branches: ["*"] + pull_request: + types: [opened, reopened, synchronize] + branches: ["*"] jobs: coverage: From a023dc21c5e4490d4d7f49a7fa18cbabb384e79e Mon Sep 17 00:00:00 2001 From: Charles Ferguson <gerph@gerph.org> Date: Sun, 11 Jan 2026 01:14:12 +0000 Subject: [PATCH 55/65] Add PR/issue templates to guide contributors --- .github/ISSUE_TEMPLATE/bug_report.md | 29 ++++++++++++++++++++++ .github/ISSUE_TEMPLATE/feature_request.md | 30 +++++++++++++++++++++++ .github/pull_request_template.md | 17 +++++++++++++ CODEOWNERS | 10 ++++++++ 4 files changed, 86 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md create mode 100644 .github/pull_request_template.md create mode 100644 CODEOWNERS diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..ab2f8e9 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,29 @@ +--- +name: Bug report +about: Something that's not right about the project +title: '' +labels: bug +assignees: '' + +--- + +## Problem statement + +<!-- Explain what you think is wrong --> + + +## Environment + +<!-- Give details about the environment in which you are running, for + example, the OS version, hardware, devices or applications that + are related to the issue --> + + +## Expected result + +<!-- Explain what you expect to happen --> + + +## Reproduction steps + +<!-- Explain how to reproduce, or which test the failure is in --> diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..0d1aa9d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,30 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: enhancement +assignees: '' + +--- + +## Is your feature request related to a problem? + +<!-- Give a clear description of what you're trying to address with + this request. + For example, "I'm always frustrated when [...]", + "It is hard to [...]" + --> + +## Describe the solution you'd like + +<!-- Give a clear description of how you the request might be + addressed. If you have ideas about how it could be implemented, + separate them from user interface changes. + --> + +## Additional context + +<!-- If you have some context, like places where this would have + helped, screenshots or mock ups of an interface, or the sort + of results you'd like to see, include them here. + --> diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..8183f28 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,17 @@ +# Changes + +<!-- Describe the changes you've made in this section. + Try to explain why they're needed and what they do. + Your reviewers will use this to decide whether the + change is sufficient and correct. + You can include pictures or diagrams in here + (see mermaid documentation on GitHub). + --> + +# Testing + +<!-- Describe the testing you have done manually to + satisfy yourself that the change works as intended. + If automated tests have been updated, state this. + Include output or pictures if necessary. + --> diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 0000000..d407fee --- /dev/null +++ b/CODEOWNERS @@ -0,0 +1,10 @@ +## +# CODEOWNERS - define who is responsible for parts of the sources +# +# See: +# https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners +# https://docs.gitlab.com/user/project/codeowners/reference/ +# + +# Default code owners - automatically assigned for reviews +* @gerph From 50d6a98dba8c063cfc3d6b79df3ff1f30b979edf Mon Sep 17 00:00:00 2001 From: Charles Ferguson <gerph@gerph.org> Date: Sun, 11 Jan 2026 01:14:17 +0000 Subject: [PATCH 56/65] Add renovate (mend.io) processing of this fork --- renovate.json | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 renovate.json diff --git a/renovate.json b/renovate.json new file mode 100644 index 0000000..146a7f7 --- /dev/null +++ b/renovate.json @@ -0,0 +1,3 @@ +{ + "forkProcessing": "enabled" +} From 20e586ad0efa10ecc56a1d10cc9921020372a84c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 11 Jan 2026 01:16:37 +0000 Subject: [PATCH 57/65] Update dependency coverage to v7 --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 10a676a..8a9b48a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1 @@ -coverage == 5.5 +coverage ==7.13.1 From 0f48d39e00408023d8f19f736dc89cd1f46c2db7 Mon Sep 17 00:00:00 2001 From: Charles Ferguson <gerph@gerph.org> Date: Sun, 11 Jan 2026 01:18:40 +0000 Subject: [PATCH 58/65] Switch to Python 3. Rather than using Python 2, I'm going to try Python 3... --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 52fa70f..c5cbb71 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,12 +24,12 @@ jobs: - name: Prepare packages run: | - sudo apt-get install -y python2 virtualenv - virtualenv -p python2 venv + sudo apt-get install -y python3 virtualenv + virtualenv -p python3 venv source venv/bin/activate && \ pip install -r requirements.txt - name: Run the coverage tests run: | source venv/bin/activate && \ - timeout 60 make coverage + timeout 180 make coverage From 6bc353818ed175ab056c1c96f61297f12db740f4 Mon Sep 17 00:00:00 2001 From: Charles Ferguson <gerph@gerph.org> Date: Sun, 11 Jan 2026 01:27:01 +0000 Subject: [PATCH 59/65] Run on Ubuntu 24. This got lost again. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c5cbb71..5760249 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,7 +18,7 @@ on: jobs: coverage: - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v3 From 92c0728be5c570bc4c691eb68c89344bf4d5e815 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 11 Jan 2026 01:28:40 +0000 Subject: [PATCH 60/65] Update actions/checkout action to v6 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5760249..d2c9eab 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,7 +20,7 @@ jobs: coverage: runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v6 - name: Prepare packages run: | From dee1032adacf2a5b4b9afb143e99113bac9e06aa Mon Sep 17 00:00:00 2001 From: Charles Ferguson <gerph@gerph.org> Date: Sun, 25 Jan 2026 18:27:27 +0000 Subject: [PATCH 61/65] Fix for missing brackets on print statement. The print statement wasn't in Python 3 format. --- RunBeebMinimal.py | 2 +- pybeeb/CPU/Memory.py | 2 +- pybeeb/Debugging/ExecutionUnit.py | 2 +- pybeeb/Debugging/Writeback.py | 16 ++++++++-------- pybeeb/Emulation.py | 2 +- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/RunBeebMinimal.py b/RunBeebMinimal.py index e2db2f7..d03453a 100755 --- a/RunBeebMinimal.py +++ b/RunBeebMinimal.py @@ -60,7 +60,7 @@ def go(self, syscalls): while True: if self.pcTrace: - print "%s: PC: %s" % (instr, hex(self.reg.pc)) + print("%s: PC: %s" % (instr, hex(self.reg.pc))) instr += 1 if not self.pcTrace and not self.verbose: diff --git a/pybeeb/CPU/Memory.py b/pybeeb/CPU/Memory.py index 29c8db5..59d2acb 100644 --- a/pybeeb/CPU/Memory.py +++ b/pybeeb/CPU/Memory.py @@ -88,7 +88,7 @@ def readByte(self, address): else: readByte = self.memory[address] - #print "Read byte %s from %s" % (hex(readByte) , hex(address)) + #print("Read byte %s from %s" % (hex(readByte) , hex(address))) return readByte def writeByte(self, address, value): diff --git a/pybeeb/Debugging/ExecutionUnit.py b/pybeeb/Debugging/ExecutionUnit.py index 4f81d2b..e5ebca6 100644 --- a/pybeeb/Debugging/ExecutionUnit.py +++ b/pybeeb/Debugging/ExecutionUnit.py @@ -6,5 +6,5 @@ def __init__(self): def __getattr__(self, name): def handler(*args, **kwargs): - print "%s called (%s, %s)" % (name, args, kwargs) + print("%s called (%s, %s)" % (name, args, kwargs)) return handler diff --git a/pybeeb/Debugging/Writeback.py b/pybeeb/Debugging/Writeback.py index 62358af..f995155 100644 --- a/pybeeb/Debugging/Writeback.py +++ b/pybeeb/Debugging/Writeback.py @@ -6,25 +6,25 @@ class LoggingDispatcher(object): def A(self, value, location): - print "Saving %s to A" % value + print("Saving %s to A" % value) def X(self, value, location): - print "Saving %s to X" % value + print("Saving %s to X" % value) def Y(self, value, location): - print "Saving %s to Y" % value + print("Saving %s to Y" % value) def memory(self, value, location): - print "Saving %s to $%s" % (value, hex(location)) + print("Saving %s to $%s" % (value, hex(location))) def PC(self, value, location): - print "Saving %s to the PC" % value + print("Saving %s to the PC" % value) def SP(self, value, location): - print "Saving %s to the SP" % value + print("Saving %s to the SP" % value) def PS(self, value, location): - print "Saving %s to the PS" % value + print("Saving %s to the PS" % value) def NW(self, value, location): - print "(no writeback)" \ No newline at end of file + print("(no writeback)") \ No newline at end of file diff --git a/pybeeb/Emulation.py b/pybeeb/Emulation.py index d39e1b8..b22b4f2 100644 --- a/pybeeb/Emulation.py +++ b/pybeeb/Emulation.py @@ -458,7 +458,7 @@ def emu_start(self, begin, until, count=0): self.regs.pc = begin try: while self.executing and self.regs.pc != until: - #print "%s: PC: %s" % (insts, hex(self.regs.pc)) + #print("%s: PC: %s" % (insts, hex(self.regs.pc))) self.bbc.tick() insts += 1 From 7e5cf4093d7753aa4b4489ec4b2106d57a16df14 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 25 Jan 2026 18:33:27 +0000 Subject: [PATCH 62/65] Update dependency coverage to v7.13.2 --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 8a9b48a..7d36ff6 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1 @@ -coverage ==7.13.1 +coverage ==7.13.2 From 9c87f4e02c58a8ee63f6b14446a45b43d9a67a66 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 3 Feb 2026 18:47:43 +0000 Subject: [PATCH 63/65] Update dependency coverage to v7.13.3 --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 7d36ff6..1105d0e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1 @@ -coverage ==7.13.2 +coverage ==7.13.3 From bdf6523dacf1fde5def4b138191dd85bae74c159 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 9 Feb 2026 13:33:13 +0000 Subject: [PATCH 64/65] Update dependency coverage to v7.13.4 --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 1105d0e..a1e6abd 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1 @@ -coverage ==7.13.3 +coverage ==7.13.4 From e8e1ac874a0d50598cf8ff71c9eb5c186e8e2a67 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 17 Mar 2026 13:16:44 +0000 Subject: [PATCH 65/65] Update dependency coverage to v7.13.5 --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index a1e6abd..7db82e2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1 @@ -coverage ==7.13.4 +coverage ==7.13.5